From f6974a92fbe923d2fef4dfac4f155b3005b7a9ba Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Tue, 7 Aug 2012 23:07:07 +1200 Subject: [PATCH 001/169] Bug 776836. When invalidating ThebesLayers due to an appunits-per-dev-pixel change, we can't trust the frame geometry. r=mattwoodrow --- layout/base/FrameLayerBuilder.cpp | 26 ++++++++++++++++++++------ layout/base/FrameLayerBuilder.h | 6 ++++++ layout/base/nsPresContext.cpp | 2 +- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp index e6c608089b22..857e6531a0bc 100644 --- a/layout/base/FrameLayerBuilder.cpp +++ b/layout/base/FrameLayerBuilder.cpp @@ -2425,16 +2425,23 @@ FrameLayerBuilder::InvalidateThebesLayerContents(nsIFrame* aFrame, * Returns true if we find a descendant with a container layer */ static bool -InternalInvalidateThebesLayersInSubtree(nsIFrame* aFrame) +InternalInvalidateThebesLayersInSubtree(nsIFrame* aFrame, bool aTrustFrameGeometry) { if (!(aFrame->GetStateBits() & NS_FRAME_HAS_CONTAINER_LAYER_DESCENDANT)) return false; bool foundContainerLayer = false; if (aFrame->GetStateBits() & NS_FRAME_HAS_CONTAINER_LAYER) { - // Delete the invalid region to indicate that all Thebes contents - // need to be invalidated - FrameLayerBuilder::InvalidateThebesLayerContents(aFrame, aFrame->GetVisualOverflowRectRelativeToSelf()); + if (aTrustFrameGeometry) { + // Just invalidate the area covered by the frame. This helps if a single + // region is being shared by multiple container layers. + FrameLayerBuilder::InvalidateThebesLayerContents(aFrame, + aFrame->GetVisualOverflowRectRelativeToSelf()); + } else { + // Delete the invalid region to indicate that all Thebes contents + // need to be invalidated + aFrame->Properties().Delete(ThebesLayerInvalidRegionProperty()); + } foundContainerLayer = true; } @@ -2457,7 +2464,8 @@ InternalInvalidateThebesLayersInSubtree(nsIFrame* aFrame) for (; !lists.IsDone(); lists.Next()) { nsFrameList::Enumerator childFrames(lists.CurrentList()); for (; !childFrames.AtEnd(); childFrames.Next()) { - if (InternalInvalidateThebesLayersInSubtree(childFrames.get())) { + if (InternalInvalidateThebesLayersInSubtree(childFrames.get(), + aTrustFrameGeometry)) { foundContainerLayer = true; } } @@ -2472,7 +2480,13 @@ InternalInvalidateThebesLayersInSubtree(nsIFrame* aFrame) /* static */ void FrameLayerBuilder::InvalidateThebesLayersInSubtree(nsIFrame* aFrame) { - InternalInvalidateThebesLayersInSubtree(aFrame); + InternalInvalidateThebesLayersInSubtree(aFrame, true); +} + +/* static */ void +FrameLayerBuilder::InvalidateThebesLayersInSubtreeWithUntrustedFrameGeometry(nsIFrame* aFrame) +{ + InternalInvalidateThebesLayersInSubtree(aFrame, false); } /* static */ void diff --git a/layout/base/FrameLayerBuilder.h b/layout/base/FrameLayerBuilder.h index 9513460235bc..1db19504e941 100644 --- a/layout/base/FrameLayerBuilder.h +++ b/layout/base/FrameLayerBuilder.h @@ -251,6 +251,12 @@ public: */ static void InvalidateThebesLayersInSubtree(nsIFrame* aFrame); + /** + * As InvalidateThebesLayersInSubtree, but don't trust frame geometry + * (e.g. because appunits-per-dev-pixel changed). + */ + static void InvalidateThebesLayersInSubtreeWithUntrustedFrameGeometry(nsIFrame* aFrame); + /** * Call this to force all retained layers to be discarded and recreated at * the next paint. diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp index 31c98d318805..1d6e96f5bb44 100644 --- a/layout/base/nsPresContext.cpp +++ b/layout/base/nsPresContext.cpp @@ -796,7 +796,7 @@ nsPresContext::InvalidateThebesLayers() // FrameLayerBuilder caches invalidation-related values that depend on the // appunits-per-dev-pixel ratio, so ensure that all ThebesLayer drawing // is completely flushed. - FrameLayerBuilder::InvalidateThebesLayersInSubtree(rootFrame); + FrameLayerBuilder::InvalidateThebesLayersInSubtreeWithUntrustedFrameGeometry(rootFrame); } } From fa8d7f9cf5ab72b5229ce03e528cf4315b43787f Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Tue, 7 Aug 2012 23:07:54 +1200 Subject: [PATCH 002/169] Bug 780582. Ensure that mouse-up/touch-end events are processed by some frame, so that capture is released. r=smaug --- layout/base/nsPresShell.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 2cd590c29182..f955837e456b 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -476,6 +476,13 @@ public: mPresShell->FlushPendingNotifications(Flush_Layout); } nsIFrame* frame = mPresShell->GetCurrentEventFrame(); + if (!frame && + (aVisitor.mEvent->message == NS_MOUSE_BUTTON_UP || + aVisitor.mEvent->message == NS_TOUCH_END)) { + // Redirect BUTTON_UP and TOUCH_END events to the root frame to ensure + // that capturing is released. + frame = mPresShell->GetRootFrame(); + } if (frame) { frame->HandleEvent(aVisitor.mPresContext, (nsGUIEvent*) aVisitor.mEvent, From 0a8452d486f938979dc15759c0b94b99e3027ac2 Mon Sep 17 00:00:00 2001 From: Lucas Rocha Date: Tue, 7 Aug 2012 15:23:20 +0100 Subject: [PATCH 003/169] Bug 766942 - Change bookmarks tab to support reading list as initial folder (r=margaret) --- mobile/android/base/awesomebar/BookmarksTab.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/mobile/android/base/awesomebar/BookmarksTab.java b/mobile/android/base/awesomebar/BookmarksTab.java index 7311c9ec6b81..e17c47820ad4 100644 --- a/mobile/android/base/awesomebar/BookmarksTab.java +++ b/mobile/android/base/awesomebar/BookmarksTab.java @@ -39,6 +39,7 @@ public class BookmarksTab extends AwesomeBarTab { private String mFolderTitle; private BookmarksListAdapter mCursorAdapter = null; private BookmarksQueryTask mQueryTask = null; + private boolean mShowReadingList = false; public int getTitleStringId() { return R.string.awesomebar_bookmarks_title; @@ -78,12 +79,21 @@ public class BookmarksTab extends AwesomeBarTab { list.setAdapter(null); list.setAdapter(getCursorAdapter()); - BookmarksQueryTask task = getQueryTask(); - task.execute(); + if (mShowReadingList) { + String title = getResources().getString(R.string.bookmarks_folder_reading_list); + getCursorAdapter().moveToChildFolder(Bookmarks.FIXED_READING_LIST_ID, title); + } else { + BookmarksQueryTask task = getQueryTask(); + task.execute(); + } } return (ListView)mView; } + public void setShowReadingList(boolean showReadingList) { + mShowReadingList = showReadingList; + } + public void destroy() { BookmarksListAdapter adapter = getCursorAdapter(); if (adapter == null) { From cd6d88fb9dcb10db1112ba12a73c5871a8aa6274 Mon Sep 17 00:00:00 2001 From: Lucas Rocha Date: Tue, 7 Aug 2012 15:23:20 +0100 Subject: [PATCH 004/169] Bug 766942 - Support showing reading list directly on awesomebar startup (r=margaret) --- mobile/android/base/AwesomeBar.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/mobile/android/base/AwesomeBar.java b/mobile/android/base/AwesomeBar.java index 90693c924d57..2f7742ebf6e9 100644 --- a/mobile/android/base/AwesomeBar.java +++ b/mobile/android/base/AwesomeBar.java @@ -6,6 +6,7 @@ package org.mozilla.gecko; import org.mozilla.gecko.db.BrowserDB; +import org.mozilla.gecko.db.BrowserContract.Bookmarks; import org.mozilla.gecko.util.GeckoAsyncTask; import android.app.Activity; @@ -58,6 +59,7 @@ public class AwesomeBar extends GeckoActivity { static final String TARGET_KEY = "target"; static final String SEARCH_KEY = "search"; static final String USER_ENTERED_KEY = "user_entered"; + static final String READING_LIST_KEY = "reading_list"; static enum Target { NEW_TAB, CURRENT_TAB }; private String mTarget; @@ -233,6 +235,13 @@ public class AwesomeBar extends GeckoActivity { } } }); + + boolean showReadingList = intent.getBooleanExtra(READING_LIST_KEY, false); + if (showReadingList) { + BookmarksTab bookmarksTab = mAwesomeTabs.getBookmarksTab(); + bookmarksTab.setShowReadingList(true); + mAwesomeTabs.setCurrentTabByTag(bookmarksTab.getTag()); + } } @Override From 0cad1e1280a8308984321d5f7b1eb443828a96d2 Mon Sep 17 00:00:00 2001 From: Lucas Rocha Date: Tue, 7 Aug 2012 15:23:20 +0100 Subject: [PATCH 005/169] Bug 766942 - Add Reader:GoToReadingList bits to GeckoApp (r=margaret) --- mobile/android/base/GeckoApp.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/mobile/android/base/GeckoApp.java b/mobile/android/base/GeckoApp.java index ba4ca6da2a30..245c008df373 100644 --- a/mobile/android/base/GeckoApp.java +++ b/mobile/android/base/GeckoApp.java @@ -902,6 +902,8 @@ abstract public class GeckoApp } else if (event.equals("Reader:FaviconRequest")) { final String url = message.getString("url"); handleFaviconRequest(url); + } else if (event.equals("Reader:GoToReadingList")) { + showReadingList(); } else if (event.equals("Content:StateChange")) { final int tabId = message.getInt("tabID"); final String uri = message.getString("uri"); @@ -1707,6 +1709,7 @@ abstract public class GeckoApp GeckoAppShell.registerGeckoEventListener("Content:LoadError", this); GeckoAppShell.registerGeckoEventListener("Content:PageShow", this); GeckoAppShell.registerGeckoEventListener("Reader:FaviconRequest", this); + GeckoAppShell.registerGeckoEventListener("Reader:GoToReadingList", this); GeckoAppShell.registerGeckoEventListener("onCameraCapture", this); GeckoAppShell.registerGeckoEventListener("Menu:Add", this); GeckoAppShell.registerGeckoEventListener("Menu:Remove", this); @@ -2070,6 +2073,7 @@ abstract public class GeckoApp GeckoAppShell.unregisterGeckoEventListener("Content:LoadError", this); GeckoAppShell.unregisterGeckoEventListener("Content:PageShow", this); GeckoAppShell.unregisterGeckoEventListener("Reader:FaviconRequest", this); + GeckoAppShell.unregisterGeckoEventListener("Reader:GoToReadingList", this); GeckoAppShell.unregisterGeckoEventListener("onCameraCapture", this); GeckoAppShell.unregisterGeckoEventListener("Menu:Add", this); GeckoAppShell.unregisterGeckoEventListener("Menu:Remove", this); @@ -2437,6 +2441,16 @@ abstract public class GeckoApp return true; } + public void showReadingList() { + Intent intent = new Intent(getBaseContext(), AwesomeBar.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION | Intent.FLAG_ACTIVITY_NO_HISTORY); + intent.putExtra(AwesomeBar.TARGET_KEY, AwesomeBar.Target.CURRENT_TAB.toString()); + intent.putExtra(AwesomeBar.READING_LIST_KEY, true); + + int requestCode = GeckoAppShell.sActivityHelper.makeRequestCodeForAwesomebar(); + startActivityForResult(intent, requestCode); + } + @Override public void onBackPressed() { if (autoHideTabs()) { From b06be6efb804e106a5ae650013c1cfe23b45038c Mon Sep 17 00:00:00 2001 From: Lucas Rocha Date: Tue, 7 Aug 2012 15:23:20 +0100 Subject: [PATCH 006/169] Bug 766942 - Set query argument with initial reading list state (r=mfinkle) --- mobile/android/base/Tab.java | 3 ++- mobile/android/base/awesomebar/AwesomeBarTab.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/mobile/android/base/Tab.java b/mobile/android/base/Tab.java index 8038329aee17..d87bdd40dade 100644 --- a/mobile/android/base/Tab.java +++ b/mobile/android/base/Tab.java @@ -449,7 +449,8 @@ public final class Tab { if (!mReaderEnabled) return; - GeckoApp.mAppContext.loadUrl("about:reader?url=" + Uri.encode(getURL())); + GeckoApp.mAppContext.loadUrl("about:reader?url=" + Uri.encode(getURL()) + + "&readingList=" + (mReadingListItem ? 1 : 0)); } public void doReload() { diff --git a/mobile/android/base/awesomebar/AwesomeBarTab.java b/mobile/android/base/awesomebar/AwesomeBarTab.java index 0803dfc0b8d6..f38c54d4f6b9 100644 --- a/mobile/android/base/awesomebar/AwesomeBarTab.java +++ b/mobile/android/base/awesomebar/AwesomeBarTab.java @@ -92,7 +92,7 @@ abstract public class AwesomeBarTab { protected String getReaderForUrl(String url) { // FIXME: still need to define the final way to open items from // reading list. For now, we're using an about:reader page. - return "about:reader?url=" + Uri.encode(url); + return "about:reader?url=" + Uri.encode(url) + "&readingList=1"; } protected void updateFavicon(ImageView faviconView, Cursor cursor) { From f675ee92d78d85b05f1d26719b603d519e0be590 Mon Sep 17 00:00:00 2001 From: Lucas Rocha Date: Tue, 7 Aug 2012 15:23:20 +0100 Subject: [PATCH 007/169] Bug 766942 - Fix GeckoApp's showToast() to actually show the notification (r=mfinkle) --- mobile/android/base/GeckoApp.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/android/base/GeckoApp.java b/mobile/android/base/GeckoApp.java index 245c008df373..d062928c387c 100644 --- a/mobile/android/base/GeckoApp.java +++ b/mobile/android/base/GeckoApp.java @@ -1264,7 +1264,7 @@ abstract public class GeckoApp public void showToast(final int resId, final int duration) { mMainHandler.post(new Runnable() { public void run() { - Toast.makeText(mAppContext, resId, duration); + Toast.makeText(mAppContext, resId, duration).show(); } }); } From 671812a343f1bfb29e37b42ff713fae6b7b6fa58 Mon Sep 17 00:00:00 2001 From: Lucas Rocha Date: Tue, 7 Aug 2012 15:23:20 +0100 Subject: [PATCH 008/169] Bug 766942 - Change Tabs to handle Reader:Removed message from Gecko (r=mfinkle) --- mobile/android/base/Tabs.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/mobile/android/base/Tabs.java b/mobile/android/base/Tabs.java index cd4a2845c7fe..0d508f1cd8f8 100644 --- a/mobile/android/base/Tabs.java +++ b/mobile/android/base/Tabs.java @@ -45,6 +45,7 @@ public class Tabs implements GeckoEventListener { GeckoAppShell.registerGeckoEventListener("Session:RestoreBegin", this); GeckoAppShell.registerGeckoEventListener("Session:RestoreEnd", this); GeckoAppShell.registerGeckoEventListener("Reader:Added", this); + GeckoAppShell.registerGeckoEventListener("Reader:Removed", this); GeckoAppShell.registerGeckoEventListener("Reader:Share", this); } @@ -273,6 +274,9 @@ public class Tabs implements GeckoEventListener { final String title = message.getString("title"); final String url = message.getString("url"); handleReaderAdded(success, title, url); + } else if (event.equals("Reader:Removed")) { + final String url = message.getString("url"); + handleReaderRemoved(url); } else if (event.equals("Reader:Share")) { final String title = message.getString("title"); final String url = message.getString("url"); @@ -299,6 +303,15 @@ public class Tabs implements GeckoEventListener { }); } + void handleReaderRemoved(final String url) { + GeckoAppShell.getHandler().post(new Runnable() { + public void run() { + BrowserDB.removeReadingListItemWithURL(mResolver, url); + mActivity.showToast(R.string.reading_list_removed, Toast.LENGTH_SHORT); + } + }); + } + public void refreshThumbnails() { Iterator iterator = mTabs.values().iterator(); while (iterator.hasNext()) { From 7363f1d34e285aa7165346db3978c1019621318e Mon Sep 17 00:00:00 2001 From: Lucas Rocha Date: Tue, 7 Aug 2012 15:23:21 +0100 Subject: [PATCH 009/169] Bug 766942 - Implement new reader toolbar (r=mfinkle) --- .../android/chrome/content/aboutReader.html | 14 +- mobile/android/chrome/content/aboutReader.js | 60 ++++++++ mobile/android/themes/core/aboutReader.css | 131 +++++++++++++++++- .../images/reader-list-icon-land-hdpi.png | Bin 0 -> 1190 bytes .../images/reader-list-icon-land-mdpi.png | Bin 0 -> 1169 bytes .../images/reader-list-icon-land-xhdpi.png | Bin 0 -> 1435 bytes .../images/reader-list-icon-port-hdpi.png | Bin 0 -> 1441 bytes .../images/reader-list-icon-port-mdpi.png | Bin 0 -> 1578 bytes .../images/reader-list-icon-port-xhdpi.png | Bin 0 -> 2022 bytes .../images/reader-list-icon-xlarge-hdpi.png | Bin 0 -> 2055 bytes .../images/reader-list-icon-xlarge-mdpi.png | Bin 0 -> 1600 bytes .../images/reader-list-icon-xlarge-xhdpi.png | Bin 0 -> 2212 bytes .../images/reader-share-icon-land-hdpi.png | Bin 2188 -> 2270 bytes .../images/reader-share-icon-land-mdpi.png | Bin 1551 -> 1666 bytes .../images/reader-share-icon-land-xhdpi.png | Bin 2543 -> 2692 bytes .../images/reader-share-icon-port-hdpi.png | Bin 2394 -> 2523 bytes .../images/reader-share-icon-port-mdpi.png | Bin 1684 -> 1810 bytes .../images/reader-share-icon-port-xhdpi.png | Bin 2960 -> 3125 bytes .../images/reader-share-icon-xlarge-hdpi.png | Bin 2643 -> 2804 bytes .../images/reader-share-icon-xlarge-mdpi.png | Bin 1966 -> 2171 bytes .../images/reader-share-icon-xlarge-xhdpi.png | Bin 3322 -> 3533 bytes .../images/reader-style-icon-land-hdpi.png | Bin 2100 -> 2210 bytes .../images/reader-style-icon-land-mdpi.png | Bin 1590 -> 1710 bytes .../images/reader-style-icon-land-xhdpi.png | Bin 2487 -> 2644 bytes .../images/reader-style-icon-port-hdpi.png | Bin 2290 -> 2445 bytes .../images/reader-style-icon-port-mdpi.png | Bin 1814 -> 1994 bytes .../images/reader-style-icon-port-xhdpi.png | Bin 2889 -> 3134 bytes .../images/reader-style-icon-xlarge-hdpi.png | Bin 2588 -> 2789 bytes .../images/reader-style-icon-xlarge-mdpi.png | Bin 1959 -> 2153 bytes .../images/reader-style-icon-xlarge-xhdpi.png | Bin 3203 -> 3414 bytes .../reader-toggle-off-icon-land-hdpi.png | Bin 0 -> 2053 bytes .../reader-toggle-off-icon-land-mdpi.png | Bin 0 -> 1656 bytes .../reader-toggle-off-icon-land-xhdpi.png | Bin 0 -> 2429 bytes .../reader-toggle-off-icon-port-hdpi.png | Bin 0 -> 2282 bytes .../reader-toggle-off-icon-port-mdpi.png | Bin 0 -> 1844 bytes .../reader-toggle-off-icon-port-xhdpi.png | Bin 0 -> 2701 bytes .../reader-toggle-off-icon-xlarge-hdpi.png | Bin 0 -> 2941 bytes .../reader-toggle-off-icon-xlarge-mdpi.png | Bin 0 -> 1978 bytes .../reader-toggle-off-icon-xlarge-xhdpi.png | Bin 0 -> 3191 bytes .../reader-toggle-on-icon-land-hdpi.png | Bin 0 -> 1936 bytes .../reader-toggle-on-icon-land-mdpi.png | Bin 0 -> 1618 bytes .../reader-toggle-on-icon-land-xhdpi.png | Bin 0 -> 2180 bytes .../reader-toggle-on-icon-port-hdpi.png | Bin 0 -> 2075 bytes .../reader-toggle-on-icon-port-mdpi.png | Bin 0 -> 1674 bytes .../reader-toggle-on-icon-port-xhdpi.png | Bin 0 -> 2288 bytes .../reader-toggle-on-icon-xlarge-hdpi.png | Bin 0 -> 2274 bytes .../reader-toggle-on-icon-xlarge-mdpi.png | Bin 0 -> 1831 bytes .../reader-toggle-on-icon-xlarge-xhdpi.png | Bin 0 -> 2757 bytes mobile/android/themes/core/jar.mn | 27 ++++ 49 files changed, 222 insertions(+), 10 deletions(-) create mode 100644 mobile/android/themes/core/images/reader-list-icon-land-hdpi.png create mode 100644 mobile/android/themes/core/images/reader-list-icon-land-mdpi.png create mode 100644 mobile/android/themes/core/images/reader-list-icon-land-xhdpi.png create mode 100644 mobile/android/themes/core/images/reader-list-icon-port-hdpi.png create mode 100644 mobile/android/themes/core/images/reader-list-icon-port-mdpi.png create mode 100644 mobile/android/themes/core/images/reader-list-icon-port-xhdpi.png create mode 100644 mobile/android/themes/core/images/reader-list-icon-xlarge-hdpi.png create mode 100644 mobile/android/themes/core/images/reader-list-icon-xlarge-mdpi.png create mode 100644 mobile/android/themes/core/images/reader-list-icon-xlarge-xhdpi.png create mode 100644 mobile/android/themes/core/images/reader-toggle-off-icon-land-hdpi.png create mode 100644 mobile/android/themes/core/images/reader-toggle-off-icon-land-mdpi.png create mode 100644 mobile/android/themes/core/images/reader-toggle-off-icon-land-xhdpi.png create mode 100644 mobile/android/themes/core/images/reader-toggle-off-icon-port-hdpi.png create mode 100644 mobile/android/themes/core/images/reader-toggle-off-icon-port-mdpi.png create mode 100644 mobile/android/themes/core/images/reader-toggle-off-icon-port-xhdpi.png create mode 100644 mobile/android/themes/core/images/reader-toggle-off-icon-xlarge-hdpi.png create mode 100644 mobile/android/themes/core/images/reader-toggle-off-icon-xlarge-mdpi.png create mode 100644 mobile/android/themes/core/images/reader-toggle-off-icon-xlarge-xhdpi.png create mode 100644 mobile/android/themes/core/images/reader-toggle-on-icon-land-hdpi.png create mode 100644 mobile/android/themes/core/images/reader-toggle-on-icon-land-mdpi.png create mode 100644 mobile/android/themes/core/images/reader-toggle-on-icon-land-xhdpi.png create mode 100644 mobile/android/themes/core/images/reader-toggle-on-icon-port-hdpi.png create mode 100644 mobile/android/themes/core/images/reader-toggle-on-icon-port-mdpi.png create mode 100644 mobile/android/themes/core/images/reader-toggle-on-icon-port-xhdpi.png create mode 100644 mobile/android/themes/core/images/reader-toggle-on-icon-xlarge-hdpi.png create mode 100644 mobile/android/themes/core/images/reader-toggle-on-icon-xlarge-mdpi.png create mode 100644 mobile/android/themes/core/images/reader-toggle-on-icon-xlarge-xhdpi.png diff --git a/mobile/android/chrome/content/aboutReader.html b/mobile/android/chrome/content/aboutReader.html index b2ed6ec6eb5e..9753c034be13 100644 --- a/mobile/android/chrome/content/aboutReader.html +++ b/mobile/android/chrome/content/aboutReader.html @@ -17,17 +17,19 @@
    - -
  • + +
  • +
diff --git a/dom/devicestorage/DeviceStorageRequestChild.cpp b/dom/devicestorage/DeviceStorageRequestChild.cpp index 996592f9de85..b072f1413573 100644 --- a/dom/devicestorage/DeviceStorageRequestChild.cpp +++ b/dom/devicestorage/DeviceStorageRequestChild.cpp @@ -36,14 +36,16 @@ DeviceStorageRequestChild::Recv__delete__(const DeviceStorageResponseValue& aVal case DeviceStorageResponseValue::TErrorResponse: { ErrorResponse r = aValue; - mRequest->FireError(r.error()); + bool allowDefault; + mRequest->FireError(r.error(), &allowDefault); break; } case DeviceStorageResponseValue::TSuccessResponse: { jsval result = StringToJsval(mRequest->GetOwner(), mFile->mPath); - mRequest->FireSuccess(result); + bool allowDefault; + mRequest->FireSuccess(result, &allowDefault); break; } @@ -65,7 +67,8 @@ DeviceStorageRequestChild::Recv__delete__(const DeviceStorageResponseValue& aVal mimeType); jsval result = BlobToJsval(mRequest->GetOwner(), blob); - mRequest->FireSuccess(result); + bool allowDefault; + mRequest->FireSuccess(result, &allowDefault); break; } diff --git a/dom/devicestorage/nsDeviceStorage.cpp b/dom/devicestorage/nsDeviceStorage.cpp index 6f0cc5498248..96ecdeffc48e 100644 --- a/dom/devicestorage/nsDeviceStorage.cpp +++ b/dom/devicestorage/nsDeviceStorage.cpp @@ -537,7 +537,8 @@ public: { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - mRequest->FireError(mError); + bool allowDefault; + mRequest->FireError(mError, &allowDefault); mRequest = nullptr; return NS_OK; } @@ -578,7 +579,8 @@ ContinueCursorEvent::Run() { cursor->mOkToCallContinue = true; } - mRequest->FireSuccess(val); + bool allowDefault; + mRequest->FireSuccess(val, &allowDefault); mRequest = nullptr; return NS_OK; } @@ -793,7 +795,8 @@ public: result = StringToJsval(mRequest->GetOwner(), mPath); } - mRequest->FireSuccess(result); + bool allowDefault; + mRequest->FireSuccess(result, &allowDefault); mRequest = nullptr; return NS_OK; } diff --git a/dom/file/ArchiveRequest.cpp b/dom/file/ArchiveRequest.cpp index 43b5734c426c..ef30eb0520e1 100644 --- a/dom/file/ArchiveRequest.cpp +++ b/dom/file/ArchiveRequest.cpp @@ -88,8 +88,10 @@ ArchiveRequest::Run() // Register this request to the reader. // When the reader is ready to return data, a 'Ready()' will be called nsresult rv = mArchiveReader->RegisterRequest(this); - if (NS_FAILED(rv)) - FireError(rv); + if (NS_FAILED(rv)) { + bool allowDefault; + FireError(rv, &allowDefault); + } } void @@ -109,8 +111,9 @@ nsresult ArchiveRequest::ReaderReady(nsTArray >& aFileList, nsresult aStatus) { + bool allowDefault; if (aStatus != NS_OK) { - FireError(aStatus); + FireError(aStatus, &allowDefault); return NS_OK; } @@ -148,10 +151,10 @@ ArchiveRequest::ReaderReady(nsTArray >& aFileList, } if (NS_SUCCEEDED(rv)) { - FireSuccess(result); + FireSuccess(result, &allowDefault); } else { - FireError(rv); + FireError(rv, &allowDefault); } return NS_OK; diff --git a/dom/file/FileRequest.cpp b/dom/file/FileRequest.cpp index 8b626fc51f8b..cdd295d077ff 100644 --- a/dom/file/FileRequest.cpp +++ b/dom/file/FileRequest.cpp @@ -62,8 +62,9 @@ FileRequest::NotifyHelperCompleted(FileHelper* aFileHelper) nsresult rv = aFileHelper->mResultCode; // If the request failed then fire error event and return. + bool allowDefault; if (NS_FAILED(rv)) { - FireError(rv); + FireError(rv, &allowDefault); return NS_OK; } @@ -93,10 +94,10 @@ FileRequest::NotifyHelperCompleted(FileHelper* aFileHelper) } if (NS_SUCCEEDED(rv)) { - FireSuccess(result); + FireSuccess(result, &allowDefault); } else { - FireError(rv); + FireError(rv, &allowDefault); } return NS_OK; From 37341d2906cb88915e2f367624ca1ef2e90ccbb6 Mon Sep 17 00:00:00 2001 From: Wes Johnston Date: Tue, 7 Aug 2012 09:48:44 -0700 Subject: [PATCH 029/169] Bug 776677 - Fire notifications when webapp installs throw errors. r=fabrice --- dom/apps/src/Webapps.js | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/dom/apps/src/Webapps.js b/dom/apps/src/Webapps.js index 775ef148941f..c87faac2f608 100644 --- a/dom/apps/src/Webapps.js +++ b/dom/apps/src/Webapps.js @@ -58,6 +58,14 @@ WebappsRegistry.prototype = { mgmt: 'r' }, + /* Fires errors on the request object. Also fires a notification if preventDefault was + * not called on the event + */ + _fireError: function fireError(aRequest, aError, aTopic) { + if (!Services.DOMRequest.fireError(aRequest, aError)) + Services.obs.notifyObservers(this, aTopic, aError); + }, + /** from https://developer.mozilla.org/en/OpenWebApps/The_Manifest * only the name property is mandatory */ @@ -87,7 +95,7 @@ WebappsRegistry.prototype = { app.installOrigin, app.installTime)); break; case "Webapps:Install:Return:KO": - Services.DOMRequest.fireError(req, msg.error || "DENIED"); + this._fireError(req, msg.error || "DENIED", "webapps-install-error"); break; case "Webapps:GetSelf:Return:OK": if (msg.apps.length) { @@ -132,7 +140,7 @@ WebappsRegistry.prototype = { try { let manifest = JSON.parse(xhr.responseText, installOrigin); if (!this.checkManifest(manifest, installOrigin)) { - Services.DOMRequest.fireError(request, "INVALID_MANIFEST"); + this._fireError(request, "INVALID_MANIFEST", "webapps-install-error"); } else { let receipts = (aParams && aParams.receipts && Array.isArray(aParams.receipts)) ? aParams.receipts : []; let categories = (aParams && aParams.categories && Array.isArray(aParams.categories)) ? aParams.categories : []; @@ -147,16 +155,16 @@ WebappsRegistry.prototype = { requestID: requestID }); } } catch(e) { - Services.DOMRequest.fireError(request, "MANIFEST_PARSE_ERROR"); + this._fireError(request, "MANIFEST_PARSE_ERROR", "webapps-install-error"); } } else { - Services.DOMRequest.fireError(request, "MANIFEST_URL_ERROR"); + this._fireError(request, "MANIFEST_URL_ERROR", "webapps-install-error"); } }).bind(this), false); xhr.addEventListener("error", (function() { - Services.DOMRequest.fireError(request, "NETWORK_ERROR"); + this._fireError(request, "NETWORK_ERROR", "webapps-install-error"); }).bind(this), false); xhr.send(null); From 9382c1dea02b46879c40a0166624a8bb5449b397 Mon Sep 17 00:00:00 2001 From: Wes Johnston Date: Tue, 7 Aug 2012 09:49:30 -0700 Subject: [PATCH 030/169] Bug 766392 - Style about:apps to match other about pages. r=mfinkle --- mobile/android/app/mobile.js | 2 +- mobile/android/chrome/content/aboutApps.js | 9 +++++ mobile/android/chrome/content/aboutApps.xhtml | 7 +++- mobile/android/themes/core/aboutApps.css | 37 ++++++++++++++++--- 4 files changed, 47 insertions(+), 8 deletions(-) diff --git a/mobile/android/app/mobile.js b/mobile/android/app/mobile.js index 7ae96e1d521e..a341d213e451 100644 --- a/mobile/android/app/mobile.js +++ b/mobile/android/app/mobile.js @@ -687,4 +687,4 @@ pref("reader.margin_size", 5); pref("reader.color_scheme", "light"); // Used to show a first-launch tip in reader -pref("reader.has_used_toolbar", false); \ No newline at end of file +pref("reader.has_used_toolbar", false); diff --git a/mobile/android/chrome/content/aboutApps.js b/mobile/android/chrome/content/aboutApps.js index 8737562354b1..be5ec2299bcb 100644 --- a/mobile/android/chrome/content/aboutApps.js +++ b/mobile/android/chrome/content/aboutApps.js @@ -28,6 +28,15 @@ var AppsUI = { shortcut: null }; +function openLink(aElement) { + try { + let formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"].getService(Ci.nsIURLFormatter); + let url = formatter.formatURLPref(aElement.getAttribute("pref")); + let BrowserApp = gChromeWin.BrowserApp; + BrowserApp.addTab(url, { selected: true, parentId: BrowserApp.selectedTab.id }); + } catch (ex) {} +} + function onLoad(aEvent) { try { let formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"].getService(Ci.nsIURLFormatter); diff --git a/mobile/android/chrome/content/aboutApps.xhtml b/mobile/android/chrome/content/aboutApps.xhtml index 310d1ffdd990..fb2b34185ef5 100644 --- a/mobile/android/chrome/content/aboutApps.xhtml +++ b/mobile/android/chrome/content/aboutApps.xhtml @@ -24,15 +24,18 @@ &aboutApps.title; - + -
+
&aboutApps.title;
+ +
+
diff --git a/mobile/android/themes/core/aboutApps.css b/mobile/android/themes/core/aboutApps.css index 192c9319c34f..917d5bbcae36 100644 --- a/mobile/android/themes/core/aboutApps.css +++ b/mobile/android/themes/core/aboutApps.css @@ -10,6 +10,33 @@ html { -moz-text-size-adjust: none; } +body { + margin: 0; +} + +.header { + color: black; + padding: 15px 0px 0px; + -moz-padding-start: 25px; + font-size: 20px; + font-weight: bold; + border-bottom: 2px solid; + min-height: 44px; + -moz-border-bottom-colors: #ff9100 #f27900; + position: relative; +} + +.header > .icon { + position: absolute; + top: 5px; + right: 15px; +} + +.app:active, +.header > .icon:active { + background-color: #febc2b; +} + #main-container { margin: 1em; padding: 1em; @@ -27,14 +54,14 @@ html { cursor: pointer; text-align: center; margin: 1em; - width: 70px; - height: 85px; - font-size: 10px; + width: 100px; + height: 121px; + font-size: 14px; } .app img { - width: 64px; - height: 64px; + width: 91px; + height: 91px; pointer-events: none; } From 209e77bb97ce69cfa7e45f86e46731c5eaced18a Mon Sep 17 00:00:00 2001 From: Jason Duell Date: Tue, 7 Aug 2012 10:03:14 -0700 Subject: [PATCH 031/169] Bug 773475 - Revert bug 584863 to keep redirect semantics cleaner. r=honza --- netwerk/protocol/http/nsHttpChannel.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index cfd29c729ae8..9de5f836b67c 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -4357,9 +4357,6 @@ nsHttpChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *context) nsresult rv; - if (mCanceled) - return mStatus; - rv = NS_CheckPortSafety(mURI); if (NS_FAILED(rv)) return rv; From f73e7537705749663ab341ca86013f0040f83e96 Mon Sep 17 00:00:00 2001 From: Wes Johnston Date: Tue, 7 Aug 2012 10:08:41 -0700 Subject: [PATCH 032/169] Backout 81a090e983d2, 8236b3579bf3, --- dom/apps/src/Webapps.js | 18 ++++------- dom/base/DOMRequest.cpp | 30 ++++++++----------- dom/base/DOMRequest.h | 9 +++--- dom/base/nsIDOMDOMRequest.idl | 6 ++-- dom/base/test/test_domrequest.html | 14 ++------- .../DeviceStorageRequestChild.cpp | 9 ++---- dom/devicestorage/nsDeviceStorage.cpp | 9 ++---- dom/file/ArchiveRequest.cpp | 13 ++++---- dom/file/FileRequest.cpp | 7 ++--- 9 files changed, 41 insertions(+), 74 deletions(-) diff --git a/dom/apps/src/Webapps.js b/dom/apps/src/Webapps.js index c87faac2f608..775ef148941f 100644 --- a/dom/apps/src/Webapps.js +++ b/dom/apps/src/Webapps.js @@ -58,14 +58,6 @@ WebappsRegistry.prototype = { mgmt: 'r' }, - /* Fires errors on the request object. Also fires a notification if preventDefault was - * not called on the event - */ - _fireError: function fireError(aRequest, aError, aTopic) { - if (!Services.DOMRequest.fireError(aRequest, aError)) - Services.obs.notifyObservers(this, aTopic, aError); - }, - /** from https://developer.mozilla.org/en/OpenWebApps/The_Manifest * only the name property is mandatory */ @@ -95,7 +87,7 @@ WebappsRegistry.prototype = { app.installOrigin, app.installTime)); break; case "Webapps:Install:Return:KO": - this._fireError(req, msg.error || "DENIED", "webapps-install-error"); + Services.DOMRequest.fireError(req, msg.error || "DENIED"); break; case "Webapps:GetSelf:Return:OK": if (msg.apps.length) { @@ -140,7 +132,7 @@ WebappsRegistry.prototype = { try { let manifest = JSON.parse(xhr.responseText, installOrigin); if (!this.checkManifest(manifest, installOrigin)) { - this._fireError(request, "INVALID_MANIFEST", "webapps-install-error"); + Services.DOMRequest.fireError(request, "INVALID_MANIFEST"); } else { let receipts = (aParams && aParams.receipts && Array.isArray(aParams.receipts)) ? aParams.receipts : []; let categories = (aParams && aParams.categories && Array.isArray(aParams.categories)) ? aParams.categories : []; @@ -155,16 +147,16 @@ WebappsRegistry.prototype = { requestID: requestID }); } } catch(e) { - this._fireError(request, "MANIFEST_PARSE_ERROR", "webapps-install-error"); + Services.DOMRequest.fireError(request, "MANIFEST_PARSE_ERROR"); } } else { - this._fireError(request, "MANIFEST_URL_ERROR", "webapps-install-error"); + Services.DOMRequest.fireError(request, "MANIFEST_URL_ERROR"); } }).bind(this), false); xhr.addEventListener("error", (function() { - this._fireError(request, "NETWORK_ERROR", "webapps-install-error"); + Services.DOMRequest.fireError(request, "NETWORK_ERROR"); }).bind(this), false); xhr.send(null); diff --git a/dom/base/DOMRequest.cpp b/dom/base/DOMRequest.cpp index 5531517e5081..7dcf3d417617 100644 --- a/dom/base/DOMRequest.cpp +++ b/dom/base/DOMRequest.cpp @@ -112,7 +112,7 @@ DOMRequest::GetError(nsIDOMDOMError** aError) } void -DOMRequest::FireSuccess(jsval aResult, bool* aDefaultActionEnabled) +DOMRequest::FireSuccess(jsval aResult) { NS_ASSERTION(!mDone, "mDone shouldn't have been set to true already!"); NS_ASSERTION(!mError, "mError shouldn't have been set!"); @@ -124,11 +124,11 @@ DOMRequest::FireSuccess(jsval aResult, bool* aDefaultActionEnabled) } mResult = aResult; - FireEvent(NS_LITERAL_STRING("success"), false, false, aDefaultActionEnabled); + FireEvent(NS_LITERAL_STRING("success"), false, false); } void -DOMRequest::FireError(const nsAString& aError, bool* aDefaultActionEnabled) +DOMRequest::FireError(const nsAString& aError) { NS_ASSERTION(!mDone, "mDone shouldn't have been set to true already!"); NS_ASSERTION(!mError, "mError shouldn't have been set!"); @@ -137,11 +137,11 @@ DOMRequest::FireError(const nsAString& aError, bool* aDefaultActionEnabled) mDone = true; mError = DOMError::CreateWithName(aError); - FireEvent(NS_LITERAL_STRING("error"), true, true, aDefaultActionEnabled); + FireEvent(NS_LITERAL_STRING("error"), true, true); } void -DOMRequest::FireError(nsresult aError, bool* aDefaultActionEnabled) +DOMRequest::FireError(nsresult aError) { NS_ASSERTION(!mDone, "mDone shouldn't have been set to true already!"); NS_ASSERTION(!mError, "mError shouldn't have been set!"); @@ -150,12 +150,11 @@ DOMRequest::FireError(nsresult aError, bool* aDefaultActionEnabled) mDone = true; mError = DOMError::CreateForNSResult(aError); - FireEvent(NS_LITERAL_STRING("error"), true, true, aDefaultActionEnabled); + FireEvent(NS_LITERAL_STRING("error"), true, true); } void -DOMRequest::FireEvent(const nsAString& aType, bool aBubble, bool aCancelable, - bool* aDefaultActionEnabled) +DOMRequest::FireEvent(const nsAString& aType, bool aBubble, bool aCancelable) { if (NS_FAILED(CheckInnerWindowCorrectness())) { return; @@ -172,7 +171,8 @@ DOMRequest::FireEvent(const nsAString& aType, bool aBubble, bool aCancelable, return; } - DispatchEvent(event, aDefaultActionEnabled); + bool dummy; + DispatchEvent(event, &dummy); } void @@ -205,24 +205,20 @@ DOMRequestService::CreateRequest(nsIDOMWindow* aWindow, NS_IMETHODIMP DOMRequestService::FireSuccess(nsIDOMDOMRequest* aRequest, - const jsval& aResult, - bool* aDefaultActionEnabled) + const jsval& aResult) { - NS_ENSURE_ARG_POINTER(aDefaultActionEnabled); NS_ENSURE_STATE(aRequest); - static_cast(aRequest)->FireSuccess(aResult, aDefaultActionEnabled); + static_cast(aRequest)->FireSuccess(aResult); return NS_OK; } NS_IMETHODIMP DOMRequestService::FireError(nsIDOMDOMRequest* aRequest, - const nsAString& aError, - bool* aDefaultActionEnabled) + const nsAString& aError) { - NS_ENSURE_ARG_POINTER(aDefaultActionEnabled); NS_ENSURE_STATE(aRequest); - static_cast(aRequest)->FireError(aError, aDefaultActionEnabled); + static_cast(aRequest)->FireError(aError); return NS_OK; } diff --git a/dom/base/DOMRequest.h b/dom/base/DOMRequest.h index b02555b431cd..74aca2687f8e 100644 --- a/dom/base/DOMRequest.h +++ b/dom/base/DOMRequest.h @@ -37,9 +37,9 @@ public: NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(DOMRequest, nsDOMEventTargetHelper) - void FireSuccess(jsval aResult, bool* aDefaultActionEnabled); - void FireError(const nsAString& aError, bool* aDefaultActionEnabled); - void FireError(nsresult aError, bool* aDefaultActionEnabled); + void FireSuccess(jsval aResult); + void FireError(const nsAString& aError); + void FireError(nsresult aError); DOMRequest(nsIDOMWindow* aWindow); DOMRequest(); @@ -52,8 +52,7 @@ public: } protected: - void FireEvent(const nsAString& aType, bool aBubble, bool aCancelable, - bool* aDefaultActionEnabled); + void FireEvent(const nsAString& aType, bool aBubble, bool aCancelable); virtual void RootResultVal(); virtual void UnrootResultVal(); diff --git a/dom/base/nsIDOMDOMRequest.idl b/dom/base/nsIDOMDOMRequest.idl index 5a8b5ad72a05..b4498633353c 100644 --- a/dom/base/nsIDOMDOMRequest.idl +++ b/dom/base/nsIDOMDOMRequest.idl @@ -21,11 +21,11 @@ interface nsIDOMDOMRequest : nsIDOMEventTarget attribute nsIDOMEventListener onerror; }; -[scriptable, builtinclass, uuid(46afe27a-d407-4eb8-95c4-aefbd2b63540)] +[scriptable, builtinclass, uuid(eebcdf29-f8fa-4c36-bbc7-2146b1cbaf7b)] interface nsIDOMRequestService : nsISupports { nsIDOMDOMRequest createRequest(in nsIDOMWindow window); - bool fireSuccess(in nsIDOMDOMRequest request, in jsval result); - bool fireError(in nsIDOMDOMRequest request, in DOMString error); + void fireSuccess(in nsIDOMDOMRequest request, in jsval result); + void fireError(in nsIDOMDOMRequest request, in DOMString error); }; diff --git a/dom/base/test/test_domrequest.html b/dom/base/test/test_domrequest.html index ad5933a92b23..1f2019efdcd5 100644 --- a/dom/base/test/test_domrequest.html +++ b/dom/base/test/test_domrequest.html @@ -35,7 +35,7 @@ var ev = null; req.onsuccess = function(e) { ev = e; } -is(reqserv.fireSuccess(req, "my result"), true, "prevent default not detected"); +reqserv.fireSuccess(req, "my result"); ok(ev, "got success event"); is(ev.type, "success", "correct type during success"); is(ev.target, req, "correct target during success"); @@ -49,7 +49,7 @@ ev = null; req.onerror = function(e) { ev = e; } -is(reqserv.fireError(req, "OhMyError"), true, "prevent default not detected"); +reqserv.fireError(req, "OhMyError"); ok(ev, "got success event"); is(ev.type, "error", "correct type during error"); is(ev.target, req, "correct target during error"); @@ -57,16 +57,6 @@ is(req.readyState, "done", "correct readyState after error"); is(req.error.name, "OhMyError", "correct error after error"); is(req.result, undefined, "correct result after error"); -// Test calling preventDefault on events -req.onsuccess = function(e) e.preventDefault(); -reqserv.fireSuccess(req, "my result"); -is(reqserv.fireSuccess(req, "my result"), false, "prevent default detected"); - -// fire error -req.onerror = function(e) e.preventDefault(); -reqserv.fireError(req, "OhMyError"); -is(reqserv.fireError(req, "OhMyError"), false, "prevent default detected"); - diff --git a/dom/devicestorage/DeviceStorageRequestChild.cpp b/dom/devicestorage/DeviceStorageRequestChild.cpp index b072f1413573..996592f9de85 100644 --- a/dom/devicestorage/DeviceStorageRequestChild.cpp +++ b/dom/devicestorage/DeviceStorageRequestChild.cpp @@ -36,16 +36,14 @@ DeviceStorageRequestChild::Recv__delete__(const DeviceStorageResponseValue& aVal case DeviceStorageResponseValue::TErrorResponse: { ErrorResponse r = aValue; - bool allowDefault; - mRequest->FireError(r.error(), &allowDefault); + mRequest->FireError(r.error()); break; } case DeviceStorageResponseValue::TSuccessResponse: { jsval result = StringToJsval(mRequest->GetOwner(), mFile->mPath); - bool allowDefault; - mRequest->FireSuccess(result, &allowDefault); + mRequest->FireSuccess(result); break; } @@ -67,8 +65,7 @@ DeviceStorageRequestChild::Recv__delete__(const DeviceStorageResponseValue& aVal mimeType); jsval result = BlobToJsval(mRequest->GetOwner(), blob); - bool allowDefault; - mRequest->FireSuccess(result, &allowDefault); + mRequest->FireSuccess(result); break; } diff --git a/dom/devicestorage/nsDeviceStorage.cpp b/dom/devicestorage/nsDeviceStorage.cpp index 96ecdeffc48e..6f0cc5498248 100644 --- a/dom/devicestorage/nsDeviceStorage.cpp +++ b/dom/devicestorage/nsDeviceStorage.cpp @@ -537,8 +537,7 @@ public: { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - bool allowDefault; - mRequest->FireError(mError, &allowDefault); + mRequest->FireError(mError); mRequest = nullptr; return NS_OK; } @@ -579,8 +578,7 @@ ContinueCursorEvent::Run() { cursor->mOkToCallContinue = true; } - bool allowDefault; - mRequest->FireSuccess(val, &allowDefault); + mRequest->FireSuccess(val); mRequest = nullptr; return NS_OK; } @@ -795,8 +793,7 @@ public: result = StringToJsval(mRequest->GetOwner(), mPath); } - bool allowDefault; - mRequest->FireSuccess(result, &allowDefault); + mRequest->FireSuccess(result); mRequest = nullptr; return NS_OK; } diff --git a/dom/file/ArchiveRequest.cpp b/dom/file/ArchiveRequest.cpp index ef30eb0520e1..43b5734c426c 100644 --- a/dom/file/ArchiveRequest.cpp +++ b/dom/file/ArchiveRequest.cpp @@ -88,10 +88,8 @@ ArchiveRequest::Run() // Register this request to the reader. // When the reader is ready to return data, a 'Ready()' will be called nsresult rv = mArchiveReader->RegisterRequest(this); - if (NS_FAILED(rv)) { - bool allowDefault; - FireError(rv, &allowDefault); - } + if (NS_FAILED(rv)) + FireError(rv); } void @@ -111,9 +109,8 @@ nsresult ArchiveRequest::ReaderReady(nsTArray >& aFileList, nsresult aStatus) { - bool allowDefault; if (aStatus != NS_OK) { - FireError(aStatus, &allowDefault); + FireError(aStatus); return NS_OK; } @@ -151,10 +148,10 @@ ArchiveRequest::ReaderReady(nsTArray >& aFileList, } if (NS_SUCCEEDED(rv)) { - FireSuccess(result, &allowDefault); + FireSuccess(result); } else { - FireError(rv, &allowDefault); + FireError(rv); } return NS_OK; diff --git a/dom/file/FileRequest.cpp b/dom/file/FileRequest.cpp index cdd295d077ff..8b626fc51f8b 100644 --- a/dom/file/FileRequest.cpp +++ b/dom/file/FileRequest.cpp @@ -62,9 +62,8 @@ FileRequest::NotifyHelperCompleted(FileHelper* aFileHelper) nsresult rv = aFileHelper->mResultCode; // If the request failed then fire error event and return. - bool allowDefault; if (NS_FAILED(rv)) { - FireError(rv, &allowDefault); + FireError(rv); return NS_OK; } @@ -94,10 +93,10 @@ FileRequest::NotifyHelperCompleted(FileHelper* aFileHelper) } if (NS_SUCCEEDED(rv)) { - FireSuccess(result, &allowDefault); + FireSuccess(result); } else { - FireError(rv, &allowDefault); + FireError(rv); } return NS_OK; From cc5567cfe33748cbe5c4e5820c314490505f5d6c Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Tue, 7 Aug 2012 19:28:00 +0200 Subject: [PATCH 033/169] Bug 780835 - Unify test manifest files with sort. r=ted --- build/macosx/universal/flight.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/build/macosx/universal/flight.mk b/build/macosx/universal/flight.mk index 59f3efc68588..0ede39352bd2 100644 --- a/build/macosx/universal/flight.mk +++ b/build/macosx/universal/flight.mk @@ -96,6 +96,7 @@ ifdef ENABLE_TESTS cp $(DIST_ARCH_1)/test-package-stage/reftest/automation.py \ $(DIST_ARCH_2)/test-package-stage/reftest/; \ $(TOPSRCDIR)/build/macosx/universal/unify \ + --unify-with-sort "\.manifest$$" \ --unify-with-sort "all-test-dirs\.list$$" \ $(DIST_ARCH_1)/test-package-stage \ $(DIST_ARCH_2)/test-package-stage \ From 938c88b25923b42979794fd32f663a5aa53a6f3f Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 7 Aug 2012 13:30:45 -0400 Subject: [PATCH 034/169] Bug 778257 - Fix javascript warning because of function returning inconsistent types. r=margaret --- mobile/android/chrome/content/browser.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index b32d0165db79..ce8d8f203d7a 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -1805,7 +1805,7 @@ var SelectionHandler = { // aX/aY are in top-level window browser coordinates endSelection: function sh_endSelection(aX, aY) { if (!this._active) - return; + return ""; this._active = false; this.hideHandles(); From 3571f68d0852ded8c1f81f73173247d7da476749 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Tue, 7 Aug 2012 10:39:45 -0700 Subject: [PATCH 035/169] Bug 779724 - Replace JSOPTION_ONLY_CNG_SOURCE with an enum on CompileOptions. r=jorendorff --- js/src/frontend/BytecodeCompiler.cpp | 17 ++++++++++++++--- js/src/jsapi.cpp | 3 ++- js/src/jsapi.h | 9 +++++++-- js/src/jsfriendapi.h | 6 ------ js/src/jsscript.cpp | 18 +++++++++--------- js/src/jsscript.h | 8 ++++++++ js/src/vm/Xdr.h | 2 +- 7 files changed, 41 insertions(+), 22 deletions(-) diff --git a/js/src/frontend/BytecodeCompiler.cpp b/js/src/frontend/BytecodeCompiler.cpp index cdb0e772d940..1b80c1754f2d 100644 --- a/js/src/frontend/BytecodeCompiler.cpp +++ b/js/src/frontend/BytecodeCompiler.cpp @@ -65,14 +65,22 @@ frontend::CompileScript(JSContext *cx, HandleObject scopeChain, StackFrame *call if (!CheckLength(cx, length)) return NULL; + JS_ASSERT_IF(staticLevel != 0, options.sourcePolicy != CompileOptions::LAZY_SOURCE); ScriptSource *ss = cx->new_(); if (!ss) return NULL; ScriptSourceHolder ssh(cx->runtime, ss); SourceCompressionToken sct(cx); - if (!cx->hasRunOption(JSOPTION_ONLY_CNG_SOURCE) || options.compileAndGo) { + switch (options.sourcePolicy) { + case CompileOptions::SAVE_SOURCE: if (!ss->setSourceCopy(cx, chars, length, false, &sct)) return NULL; + break; + case CompileOptions::LAZY_SOURCE: + ss->setSourceRetrievable(); + break; + case CompileOptions::NO_SOURCE: + break; } Parser parser(cx, options, chars, length, /* foldConstants = */ true); @@ -236,8 +244,11 @@ frontend::CompileFunctionBody(JSContext *cx, HandleFunction fun, CompileOptions return NULL; ScriptSourceHolder ssh(cx->runtime, ss); SourceCompressionToken sct(cx); - if (!ss->setSourceCopy(cx, chars, length, true, &sct)) - return NULL; + JS_ASSERT(options.sourcePolicy != CompileOptions::LAZY_SOURCE); + if (options.sourcePolicy == CompileOptions::SAVE_SOURCE) { + if (!ss->setSourceCopy(cx, chars, length, true, &sct)) + return NULL; + } options.setCompileAndGo(false); Parser parser(cx, options, chars, length, /* foldConstants = */ true); diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 8efd33808403..60834c70d808 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -5146,7 +5146,8 @@ JS::CompileOptions::CompileOptions(JSContext *cx) lineno(1), compileAndGo(cx->hasRunOption(JSOPTION_COMPILE_N_GO)), noScriptRval(cx->hasRunOption(JSOPTION_NO_SCRIPT_RVAL)), - allowIntrinsicsCalls(false) + allowIntrinsicsCalls(false), + sourcePolicy(SAVE_SOURCE) { } diff --git a/js/src/jsapi.h b/js/src/jsapi.h index d6b8e604fe29..f41020231d16 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -3221,12 +3221,11 @@ JS_StringToVersion(const char *string); strict mode for all code without requiring "use strict" annotations. */ -/* JS_BIT(20) is taken in jsfriendapi.h! */ /* Options which reflect compile-time properties of scripts. */ #define JSCOMPILEOPTION_MASK (JSOPTION_ALLOW_XML | JSOPTION_MOAR_XML) -#define JSRUNOPTION_MASK (JS_BITMASK(21) & ~JSCOMPILEOPTION_MASK) +#define JSRUNOPTION_MASK (JS_BITMASK(20) & ~JSCOMPILEOPTION_MASK) #define JSALLOPTION_MASK (JSCOMPILEOPTION_MASK | JSRUNOPTION_MASK) extern JS_PUBLIC_API(uint32_t) @@ -5081,6 +5080,11 @@ struct JS_PUBLIC_API(CompileOptions) { bool compileAndGo; bool noScriptRval; bool allowIntrinsicsCalls; + enum SourcePolicy { + NO_SOURCE, + LAZY_SOURCE, + SAVE_SOURCE + } sourcePolicy; CompileOptions(JSContext *cx); CompileOptions &setPrincipals(JSPrincipals *p) { principals = p; return *this; } @@ -5093,6 +5097,7 @@ struct JS_PUBLIC_API(CompileOptions) { CompileOptions &setCompileAndGo(bool cng) { compileAndGo = cng; return *this; } CompileOptions &setNoScriptRval(bool nsr) { noScriptRval = nsr; return *this; } CompileOptions &setAllowIntrinsicsCalls(bool aic) { allowIntrinsicsCalls = aic; return *this; } + CompileOptions &setSourcePolicy(SourcePolicy sp) { sourcePolicy = sp; return *this; } }; extern JS_PUBLIC_API(JSScript *) diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index 856c6207f7ee..eb64565044e6 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -15,12 +15,6 @@ JS_BEGIN_EXTERN_C -/* - * Only save the source of scripts that are compileAndGo or are created with - * JS_CompileFunction*. - */ -#define JSOPTION_ONLY_CNG_SOURCE JS_BIT(20) - extern JS_FRIEND_API(void) JS_SetGrayGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data); diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index c118689747df..894e20c686fd 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -361,7 +361,6 @@ js::XDRScript(XDRState *xdr, HandleObject enclosingScope, HandleScript enc IsGenerator, IsGeneratorExp, OwnSource, - HasSourceData, ExplicitUseStrict }; @@ -521,11 +520,8 @@ js::XDRScript(XDRState *xdr, HandleObject enclosingScope, HandleScript enc ? (1 << ParentFilename) : (1 << OwnFilename); } - if (!enclosingScript || enclosingScript->scriptSource() != script->scriptSource()) { + if (!enclosingScript || enclosingScript->scriptSource() != script->scriptSource()) scriptBits |= (1 << OwnSource); - if (script->scriptSource()->hasSourceData()) - scriptBits |= (1 << HasSourceData); - } if (script->isGenerator) scriptBits |= (1 << IsGenerator); if (script->isGeneratorExp) @@ -646,8 +642,7 @@ js::XDRScript(XDRState *xdr, HandleObject enclosingScope, HandleScript enc script->filename = enclosingScript->filename; } - if (scriptBits & (1 << HasSourceData)) { - JS_ASSERT(scriptBits & (1 << OwnSource)); + if (scriptBits & (1 << OwnSource)) { if (!script->scriptSource()->performXDR(xdr)) return false; } @@ -1138,7 +1133,7 @@ JSScript::loadSource(JSContext *cx, bool *worked) { JS_ASSERT(!scriptSource_->hasSourceData()); *worked = false; - if (!cx->runtime->sourceHook) + if (!cx->runtime->sourceHook || !scriptSource_->sourceRetrievable()) return true; jschar *src = NULL; uint32_t length; @@ -1314,7 +1309,12 @@ ScriptSource::performXDR(XDRState *xdr) if (!xdr->codeUint8(&hasSource)) return false; - if (hasSource) { + uint8_t retrievable = sourceRetrievable_; + if (!xdr->codeUint8(&retrievable)) + return false; + sourceRetrievable_ = retrievable; + + if (hasSource && !sourceRetrievable_) { // Only set members when we know decoding cannot fail. This prevents the // script source from being partially initialized. uint32_t length = length_; diff --git a/js/src/jsscript.h b/js/src/jsscript.h index 08d3bc16021b..e8585e3d809f 100644 --- a/js/src/jsscript.h +++ b/js/src/jsscript.h @@ -989,6 +989,11 @@ struct ScriptSource uint32_t refs; uint32_t length_; uint32_t compressedLength_; + + // True if we can call JSRuntime::sourceHook to load the source on + // demand. If sourceRetrievable_ and hasSourceData() are false, it is not + // possible to get source at all. + bool sourceRetrievable_:1; bool argumentsNotIncluded_:1; #ifdef DEBUG bool ready_:1; @@ -999,6 +1004,7 @@ struct ScriptSource : refs(0), length_(0), compressedLength_(0), + sourceRetrievable_(false), argumentsNotIncluded_(false) #ifdef DEBUG ,ready_(true) @@ -1021,6 +1027,8 @@ struct ScriptSource #ifdef DEBUG bool ready() const { return ready_; } #endif + void setSourceRetrievable() { sourceRetrievable_ = true; } + bool sourceRetrievable() const { return sourceRetrievable_; } bool hasSourceData() const { return !!data.source; } uint32_t length() const { JS_ASSERT(hasSourceData()); diff --git a/js/src/vm/Xdr.h b/js/src/vm/Xdr.h index 5cf9ed585e63..c524f31e1ca8 100644 --- a/js/src/vm/Xdr.h +++ b/js/src/vm/Xdr.h @@ -25,7 +25,7 @@ namespace js { * and saved versions. If deserialization fails, the data should be * invalidated if possible. */ -static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 127); +static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 128); class XDRBuffer { public: From f1b4836bc87de1104e8eecdab7946d90192f92e3 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Tue, 7 Aug 2012 10:39:47 -0700 Subject: [PATCH 036/169] Bug 779724 - Use finer-grain source controls in the browser. r=jorendorff, sr=jst --- content/xul/content/src/nsXULElement.cpp | 18 +++--- dom/base/nsIScriptContext.h | 8 ++- dom/base/nsJSEnvironment.cpp | 60 +++++++++++--------- dom/base/nsJSEnvironment.h | 3 +- js/xpconnect/loader/mozJSComponentLoader.cpp | 26 ++++----- js/xpconnect/loader/mozJSSubScriptLoader.cpp | 14 +++-- 6 files changed, 68 insertions(+), 61 deletions(-) diff --git a/content/xul/content/src/nsXULElement.cpp b/content/xul/content/src/nsXULElement.cpp index c93079a88ae2..acc64a8886b6 100644 --- a/content/xul/content/src/nsXULElement.cpp +++ b/content/xul/content/src/nsXULElement.cpp @@ -2497,14 +2497,12 @@ nsXULPrototypeScript::Compile(const PRUnichar* aText, // Ok, compile it to create a prototype script object! nsScriptObjectHolder newScriptObject(context); - uint32_t opts = JS_GetOptions(context->GetNativeContext()); - if (!mOutOfLine) { - // If the script was inline, tell the JS parser to save source for - // Function.prototype.toSource(). If it's outline, we retrieve the - // source from the files on demand. - opts &= ~JSOPTION_ONLY_CNG_SOURCE; - JS_SetOptions(context->GetNativeContext(), opts); - } + + // If the script was inline, tell the JS parser to save source for + // Function.prototype.toSource(). If it's out of line, we retrieve the + // source from the files on demand. + bool saveSource = !mOutOfLine; + rv = context->CompileScript(aText, aTextLength, // Use the enclosing document's principal @@ -2517,8 +2515,8 @@ nsXULPrototypeScript::Compile(const PRUnichar* aText, urlspec.get(), aLineNo, mLangVersion, - newScriptObject); - JS_SetOptions(context->GetNativeContext(), opts); + newScriptObject, + saveSource); if (NS_FAILED(rv)) return rv; diff --git a/dom/base/nsIScriptContext.h b/dom/base/nsIScriptContext.h index b54a009cc3f4..091565105af7 100644 --- a/dom/base/nsIScriptContext.h +++ b/dom/base/nsIScriptContext.h @@ -45,8 +45,8 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptContextPrincipal, NS_ISCRIPTCONTEXTPRINCIPAL_IID) #define NS_ISCRIPTCONTEXT_IID \ -{ 0x9a4df96d, 0xa231, 0x4108, \ - { 0xb5, 0xbc, 0xaf, 0x67, 0x7a, 0x36, 0xa7, 0x44 } } +{ 0x8bdcea47, 0x6704, 0x4dd9, \ + { 0xa1, 0x48, 0x05, 0x34, 0xcf, 0xe2, 0xdd, 0x57 } } /* This MUST match JSVERSION_DEFAULT. This version stuff if we don't know what language we have is a little silly... */ @@ -114,6 +114,7 @@ public: * @param aVersion the script language version to use when executing * @param aScriptObject an executable object that's the result of compiling * the script. + * @param aSaveSource force the source code to be saved by the JS engine in memory * * @return NS_OK if the script source was valid and got compiled. * @@ -124,7 +125,8 @@ public: const char* aURL, PRUint32 aLineNo, PRUint32 aVersion, - nsScriptObjectHolder& aScriptObject) = 0; + nsScriptObjectHolder& aScriptObject, + bool aSaveSource = false) = 0; /** * Execute a precompiled script object. diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index a7d9f7f7ee08..657d3a903412 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -1074,21 +1074,6 @@ nsJSContext::nsJSContext(JSRuntime *aRuntime) mDefaultJSOptions = JSOPTION_PRIVATE_IS_NSISUPPORTS | JSOPTION_ALLOW_XML; - // The JS engine needs to keep the source code around in order to implement - // Function.prototype.toSource(). JSOPTION_ONLY_CNG_SOURCE causes the JS - // engine to retain the source code for scripts compiled in compileAndGo mode - // and compiled function bodies (from JS_CompileFunction*). In practice, this - // means content scripts and event handlers. It'd be nice to stop there and - // simply stub out requests for source on chrome code. Life is not so easy, - // unfortunately. Nobody relies on chrome toSource() working in core browser - // code, but chrome tests use it. The worst offenders are addons, which like - // to monkeypatch chrome functions by calling toSource() on them and using - // regular expression to modify them. So, even though we don't keep it in - // memory, we have to provide a way to get chrome source somehow. Enter - // SourceHook. When the JS engine is asked to provide the source for a - // function it doesn't have in memory, it calls this function to load it. - mDefaultJSOptions |= JSOPTION_ONLY_CNG_SOURCE; - mContext = ::JS_NewContext(aRuntime, gStackSize); if (mContext) { ::JS_SetContextPrivate(mContext, static_cast(this)); @@ -1555,7 +1540,8 @@ nsJSContext::CompileScript(const PRUnichar* aText, const char *aURL, PRUint32 aLineNo, PRUint32 aVersion, - nsScriptObjectHolder& aScriptObject) + nsScriptObjectHolder& aScriptObject, + bool aSaveSource /* = false */) { NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED); @@ -1582,15 +1568,20 @@ nsJSContext::CompileScript(const PRUnichar* aText, XPCAutoRequest ar(mContext); - JSScript* script = - ::JS_CompileUCScriptForPrincipalsVersion(mContext, - scopeObject, - nsJSPrincipals::get(aPrincipal), - static_cast(aText), - aTextLength, - aURL, - aLineNo, - JSVersion(aVersion)); + JS::CompileOptions options(mContext); + JS::CompileOptions::SourcePolicy sp = aSaveSource ? + JS::CompileOptions::SAVE_SOURCE : + JS::CompileOptions::LAZY_SOURCE; + options.setPrincipals(nsJSPrincipals::get(aPrincipal)) + .setFileAndLine(aURL, aLineNo) + .setVersion(JSVersion(aVersion)) + .setSourcePolicy(sp); + JS::RootedObject rootedScope(mContext, scopeObject); + JSScript* script = JS::Compile(mContext, + rootedScope, + options, + static_cast(aText), + aTextLength); if (!script) { return NS_ERROR_OUT_OF_MEMORY; } @@ -3944,8 +3935,7 @@ ReadSourceFromFilename(JSContext *cx, const char *filename, jschar **src, PRUint /* The JS engine calls this function when it needs the source for a chrome JS - function. See the comment in nsJSContext::nsJSContext about - JSOPTION_ONLY_CGN_SOURCE. + function. See the comment in nsJSRuntime::Init(). */ static bool SourceHook(JSContext *cx, JSScript *script, jschar **src, uint32_t *length) @@ -3992,6 +3982,22 @@ nsJSRuntime::Init() rv = sRuntimeService->GetRuntime(&sRuntime); NS_ENSURE_SUCCESS(rv, rv); + // The JS engine needs to keep the source code around in order to implement + // Function.prototype.toSource(). It'd be nice to not have to do this for + // chrome code and simply stub out requests for source on it. Life is not so + // easy, unfortunately. Nobody relies on chrome toSource() working in core + // browser code, but chrome tests use it. The worst offenders are addons, + // which like to monkeypatch chrome functions by calling toSource() on them + // and using regular expressions to modify them. We avoid keeping most browser + // JS source code in memory by setting LAZY_SOURCE on JS::CompileOptions when + // compiling some chrome code. This causes the JS engine not save the source + // code in memory. When the JS engine is asked to provide the source for a + // function compiled with LAZY_SOURCE, it calls SourceHook to load it. + /// + // Note we do have to retain the source code in memory for scripts compiled in + // compileAndGo mode and compiled function bodies (from + // JS_CompileFunction*). In practice, this means content scripts and event + // handlers. JS_SetSourceHook(sRuntime, SourceHook); // Let's make sure that our main thread is the same as the xpcom main thread. diff --git a/dom/base/nsJSEnvironment.h b/dom/base/nsJSEnvironment.h index 3b0f29ebcff1..8af49d0a6e3d 100644 --- a/dom/base/nsJSEnvironment.h +++ b/dom/base/nsJSEnvironment.h @@ -72,7 +72,8 @@ public: const char *aURL, PRUint32 aLineNo, PRUint32 aVersion, - nsScriptObjectHolder& aScriptObject); + nsScriptObjectHolder& aScriptObject, + bool aSaveSource = false); virtual nsresult ExecuteScript(JSScript* aScriptObject, JSObject* aScopeObject, nsAString* aRetValue, diff --git a/js/xpconnect/loader/mozJSComponentLoader.cpp b/js/xpconnect/loader/mozJSComponentLoader.cpp index c8477a7ae004..49fb6b99411c 100644 --- a/js/xpconnect/loader/mozJSComponentLoader.cpp +++ b/js/xpconnect/loader/mozJSComponentLoader.cpp @@ -738,8 +738,15 @@ mozJSComponentLoader::GlobalForLocation(nsIFile *aComponentFile, // any exceptions out to our caller. Ensure that the engine doesn't // eagerly report the exception. uint32_t oldopts = JS_GetOptions(cx); - JS_SetOptions(cx, oldopts | JSOPTION_NO_SCRIPT_RVAL | - (exception ? JSOPTION_DONT_REPORT_UNCAUGHT : 0)); + if (exception) + JS_SetOptions(cx, oldopts | JSOPTION_DONT_REPORT_UNCAUGHT); + JS::CompileOptions options(cx); + options.setPrincipals(nsJSPrincipals::get(mSystemPrincipal)) + .setNoScriptRval(true) + .setVersion(JSVERSION_LATEST) + .setFileAndLine(nativePath.get(), 1) + .setSourcePolicy(JS::CompileOptions::LAZY_SOURCE); + JS::RootedObject rootedGlobal(cx, global); if (realFile) { #ifdef HAVE_PR_MEMMAP @@ -789,10 +796,7 @@ mozJSComponentLoader::GlobalForLocation(nsIFile *aComponentFile, return NS_ERROR_FAILURE; } - script = JS_CompileScriptForPrincipalsVersion(cx, global, - nsJSPrincipals::get(mSystemPrincipal), - buf, fileSize32, nativePath.get(), 1, - JSVERSION_LATEST); + script = JS::Compile(cx, rootedGlobal, options, buf, fileSize32); PR_MemUnmap(buf, fileSize32); @@ -834,10 +838,7 @@ mozJSComponentLoader::GlobalForLocation(nsIFile *aComponentFile, NS_WARNING("Failed to read file"); return NS_ERROR_FAILURE; } - script = JS_CompileScriptForPrincipalsVersion(cx, global, - nsJSPrincipals::get(mSystemPrincipal), - buf, rlen, nativePath.get(), 1, - JSVERSION_LATEST); + script = JS::Compile(cx, rootedGlobal, options, buf, rlen); free(buf); @@ -873,10 +874,7 @@ mozJSComponentLoader::GlobalForLocation(nsIFile *aComponentFile, buf[len] = '\0'; - script = JS_CompileScriptForPrincipalsVersion(cx, global, - nsJSPrincipals::get(mSystemPrincipal), - buf, bytesRead, nativePath.get(), 1, - JSVERSION_LATEST); + script = JS::Compile(cx, rootedGlobal, options, buf, bytesRead); } // Propagate the exception, if one exists. Also, don't leave the stale // exception on this context. diff --git a/js/xpconnect/loader/mozJSSubScriptLoader.cpp b/js/xpconnect/loader/mozJSSubScriptLoader.cpp index b3d73ba916d3..152ee99557d3 100644 --- a/js/xpconnect/loader/mozJSSubScriptLoader.cpp +++ b/js/xpconnect/loader/mozJSSubScriptLoader.cpp @@ -109,6 +109,11 @@ mozJSSubScriptLoader::ReadScript(nsIURI *uri, JSContext *cx, JSObject *target_ob * exceptions, including the source/line number */ er = JS_SetErrorReporter(cx, mozJSLoaderErrorReporter); + JS::CompileOptions options(cx); + options.setPrincipals(nsJSPrincipals::get(principal)) + .setFileAndLine(uriStr, 1) + .setSourcePolicy(JS::CompileOptions::LAZY_SOURCE); + JS::RootedObject target_obj_root(cx, target_obj); if (!charset.IsVoid()) { nsString script; rv = nsScriptLoader::ConvertToUTF16(nullptr, reinterpret_cast(buf.get()), len, @@ -118,13 +123,10 @@ mozJSSubScriptLoader::ReadScript(nsIURI *uri, JSContext *cx, JSObject *target_ob return ReportError(cx, LOAD_ERROR_BADCHARSET); } - *scriptp = - JS_CompileUCScriptForPrincipals(cx, target_obj, nsJSPrincipals::get(principal), - reinterpret_cast(script.get()), - script.Length(), uriStr, 1); + *scriptp = JS::Compile(cx, target_obj_root, options, + reinterpret_cast(script.get()), script.Length()); } else { - *scriptp = JS_CompileScriptForPrincipals(cx, target_obj, nsJSPrincipals::get(principal), - buf.get(), len, uriStr, 1); + *scriptp = JS::Compile(cx, target_obj_root, options, buf.get(), len); } /* repent for our evil deeds */ From a45255e781916509b332160b14cf7d5a5db5b7da Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Tue, 7 Aug 2012 09:50:52 -0700 Subject: [PATCH 037/169] Bug 780712 - CrossCompartmentWrapper needs to handle regexp_toShared (r=billm) --HG-- extra : rebase_source : 5b96cf124a0227c8a147a2c1b2306358473a8bf0 --- js/src/jit-test/tests/basic/testBug780712.js | 9 +++++++++ js/src/jswrapper.cpp | 10 ++++++++++ js/src/jswrapper.h | 1 + 3 files changed, 20 insertions(+) create mode 100644 js/src/jit-test/tests/basic/testBug780712.js diff --git a/js/src/jit-test/tests/basic/testBug780712.js b/js/src/jit-test/tests/basic/testBug780712.js new file mode 100644 index 000000000000..25df27b40c4d --- /dev/null +++ b/js/src/jit-test/tests/basic/testBug780712.js @@ -0,0 +1,9 @@ +r = evalcx("/x/", undefined); +s = ""; +gc() +Function("\ + s.match(r);\ + schedulegc(__proto__);\ + ({c:schedulegc(2)});\ + s.match(r);\ +")() diff --git a/js/src/jswrapper.cpp b/js/src/jswrapper.cpp index faae0df6be99..23840eddf8a9 100644 --- a/js/src/jswrapper.cpp +++ b/js/src/jswrapper.cpp @@ -832,6 +832,16 @@ CrossCompartmentWrapper::fun_toString(JSContext *cx, JSObject *wrapper, unsigned return str; } +bool +CrossCompartmentWrapper::regexp_toShared(JSContext *cx, JSObject *wrapper, RegExpGuard *g) +{ + AutoCompartment call(cx, wrappedObject(wrapper)); + if (!call.enter()) + return false; + + return DirectWrapper::regexp_toShared(cx, wrapper, g); +} + bool CrossCompartmentWrapper::defaultValue(JSContext *cx, JSObject *wrapper, JSType hint, Value *vp) { diff --git a/js/src/jswrapper.h b/js/src/jswrapper.h index ea775ef59f22..95d00e1881f3 100644 --- a/js/src/jswrapper.h +++ b/js/src/jswrapper.h @@ -249,6 +249,7 @@ class JS_FRIEND_API(CrossCompartmentWrapper) : public DirectWrapper virtual bool hasInstance(JSContext *cx, JSObject *wrapper, const Value *vp, bool *bp) MOZ_OVERRIDE; virtual JSString *obj_toString(JSContext *cx, JSObject *wrapper) MOZ_OVERRIDE; virtual JSString *fun_toString(JSContext *cx, JSObject *wrapper, unsigned indent) MOZ_OVERRIDE; + virtual bool regexp_toShared(JSContext *cx, JSObject *proxy, RegExpGuard *g) MOZ_OVERRIDE; virtual bool defaultValue(JSContext *cx, JSObject *wrapper, JSType hint, Value *vp) MOZ_OVERRIDE; virtual bool iteratorNext(JSContext *cx, JSObject *wrapper, Value *vp); From 3e0f6995e1f9f8721e168b126659566aaf3d7e4e Mon Sep 17 00:00:00 2001 From: Marshall Culpepper Date: Tue, 7 Aug 2012 12:26:44 -0500 Subject: [PATCH 038/169] Bug 780739: Add -Wno-psabi to suppress B2G va_list mangling warnings. r=ted --HG-- extra : rebase_source : 478202943d2a754f4d76f78cf7ddb2f60c2feb75 --- configure.in | 2 +- js/src/configure.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 3499a0a31294..fb862d752b8b 100644 --- a/configure.in +++ b/configure.in @@ -194,7 +194,7 @@ if test -n "$gonkdir" ; then CPPFLAGS="-DANDROID -isystem $gonkdir/bionic/libc/$ARCH_DIR/include -isystem $gonkdir/bionic/libc/include/ -isystem $gonkdir/bionic/libc/kernel/common -isystem $gonkdir/bionic/libc/kernel/$ARCH_DIR -isystem $gonkdir/bionic/libm/include -I$gonkdir/frameworks/base/opengl/include -I$gonkdir/frameworks/base/native/include -I$gonkdir/hardware/libhardware/include -I$gonkdir/hardware/libhardware_legacy/include -I$gonkdir/system -I$gonkdir/system/core/include -isystem $gonkdir/bionic -I$gonkdir/frameworks/base/include -I$gonkdir/external/dbus $CPPFLAGS -I$gonkdir/frameworks/base/services/sensorservice -I$gonkdir/frameworks/base/services/camera" CFLAGS="-mandroid -fno-short-enums -fno-exceptions $CFLAGS" - CXXFLAGS="-mandroid -fno-short-enums -fno-exceptions $CXXFLAGS $STLPORT_CPPFLAGS" + CXXFLAGS="-mandroid -fno-short-enums -fno-exceptions -Wno-psabi $CXXFLAGS $STLPORT_CPPFLAGS" dnl Add -llog by default, since we use it all over the place. LIBS="$LIBS -llog $STLPORT_LIBS" diff --git a/js/src/configure.in b/js/src/configure.in index 42e5a2eb5664..c4bc28550292 100644 --- a/js/src/configure.in +++ b/js/src/configure.in @@ -182,7 +182,7 @@ if test -n "$gonkdir" ; then CPPFLAGS="-DANDROID -isystem $gonkdir/bionic/libc/$ARCH_DIR/include -isystem $gonkdir/bionic/libc/include/ -isystem $gonkdir/bionic/libc/kernel/common -isystem $gonkdir/bionic/libc/kernel/$ARCH_DIR -isystem $gonkdir/bionic/libm/include -I$gonkdir/frameworks/base/native/include -I$gonkdir/system/core/include -isystem $gonkdir/bionic $CPPFLAGS" CFLAGS="-mandroid -fno-short-enums -fno-exceptions $CFLAGS" - CXXFLAGS="-mandroid -fno-short-enums -fno-exceptions $CXXFLAGS $STLPORT_CPPFLAGS" + CXXFLAGS="-mandroid -fno-short-enums -fno-exceptions -Wno-psabi $CXXFLAGS $STLPORT_CPPFLAGS" LIBS="$LIBS $STLPORT_LIBS" dnl Add -llog by default, since we use it all over the place. From 86ed7a66f68cb7a83dfaa62032398e32dcf7d34e Mon Sep 17 00:00:00 2001 From: Chris Lord Date: Tue, 7 Aug 2012 18:57:19 +0100 Subject: [PATCH 039/169] Bug 780928 - Fix rawtypes usage in LayerView.java. r=kats Fix unnecessary usage of raw Class type. --- mobile/android/base/gfx/LayerView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/android/base/gfx/LayerView.java b/mobile/android/base/gfx/LayerView.java index 656de9b9fba3..06c8d80e7980 100644 --- a/mobile/android/base/gfx/LayerView.java +++ b/mobile/android/base/gfx/LayerView.java @@ -67,7 +67,7 @@ public class LayerView extends FrameLayout { try { // and then we can only use it if we have a hardware accelerated window - Method m = View.class.getMethod("isHardwareAccelerated", new Class[0]); + Method m = View.class.getMethod("isHardwareAccelerated", (Class[]) null); return (Boolean) m.invoke(this); } catch (Exception e) { Log.i(LOGTAG, "Not using TextureView: caught exception checking for hw accel: " + e.toString()); From e7e6823aa8e980b618b991fade288cb93fcfee51 Mon Sep 17 00:00:00 2001 From: Chris Lord Date: Tue, 7 Aug 2012 18:57:26 +0100 Subject: [PATCH 040/169] Bug 775431 - Make MOZ_DUMP_PAINT_LIST output terminal-friendly. r=mattwoodrow Only output in HTML if we're dumping to a file, otherwise output as it did before the HTML output change was made. --- gfx/layers/Layers.cpp | 66 ++++++++++++++++++++----------- gfx/layers/Layers.h | 4 +- layout/base/FrameLayerBuilder.cpp | 4 +- layout/base/FrameLayerBuilder.h | 4 +- layout/base/nsLayoutDebugger.cpp | 45 +++++++++++++++------ layout/base/nsLayoutUtils.cpp | 19 +++++---- layout/generic/nsFrame.h | 3 +- 7 files changed, 96 insertions(+), 49 deletions(-) diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index 781e11a83f58..ecee25fe6718 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -871,17 +871,21 @@ void WriteSnapshotToDumpFile(LayerManager* aManager, gfxASurface* aSurf) #endif void -Layer::Dump(FILE* aFile, const char* aPrefix) +Layer::Dump(FILE* aFile, const char* aPrefix, bool aDumpHtml) { - fprintf(aFile, "
  • "); + fprintf(aFile, ">"); + } DumpSelf(aFile, aPrefix); - fprintf(aFile, ""); + if (aDumpHtml) { + fprintf(aFile, ""); + } if (Layer* mask = GetMaskLayer()) { nsCAutoString pfx(aPrefix); @@ -892,14 +896,20 @@ Layer::Dump(FILE* aFile, const char* aPrefix) if (Layer* kid = GetFirstChild()) { nsCAutoString pfx(aPrefix); pfx += " "; - fprintf(aFile, "
      "); + if (aDumpHtml) { + fprintf(aFile, "
        "); + } kid->Dump(aFile, pfx.get()); - fprintf(aFile, "
      "); + if (aDumpHtml) { + fprintf(aFile, "
    "); + } } - fprintf(aFile, "
  • "); + if (aDumpHtml) { + fprintf(aFile, ""); + } if (Layer* next = GetNextSibling()) - next->Dump(aFile, aPrefix); + next->Dump(aFile, aPrefix, aDumpHtml); } void @@ -1059,30 +1069,42 @@ ReadbackLayer::PrintInfo(nsACString& aTo, const char* aPrefix) // LayerManager void -LayerManager::Dump(FILE* aFile, const char* aPrefix) +LayerManager::Dump(FILE* aFile, const char* aPrefix, bool aDumpHtml) { FILE* file = FILEOrDefault(aFile); - fprintf(file, "", pfx.get()); + fprintf(file, "%s(null)", pfx.get()); + if (aDumpHtml) { + fprintf(file, ""); + } return; } - fprintf(file, "
      "); - GetRoot()->Dump(file, pfx.get()); - fprintf(file, "
    "); + if (aDumpHtml) { + fprintf(file, "
      "); + } + GetRoot()->Dump(file, pfx.get(), aDumpHtml); + if (aDumpHtml) { + fprintf(file, "
    "); + } + fputc('\n', file); } void @@ -1161,7 +1183,7 @@ PrintInfo(nsACString& aTo, ShadowLayer* aShadowLayer) #else // !MOZ_LAYERS_HAVE_LOG -void Layer::Dump(FILE* aFile, const char* aPrefix) {} +void Layer::Dump(FILE* aFile, const char* aPrefix, bool aDumpHtml) {} void Layer::DumpSelf(FILE* aFile, const char* aPrefix) {} void Layer::Log(const char* aPrefix) {} void Layer::LogSelf(const char* aPrefix) {} @@ -1197,7 +1219,7 @@ nsACString& ReadbackLayer::PrintInfo(nsACString& aTo, const char* aPrefix) { return aTo; } -void LayerManager::Dump(FILE* aFile, const char* aPrefix) {} +void LayerManager::Dump(FILE* aFile, const char* aPrefix, bool aDumpHtml) {} void LayerManager::DumpSelf(FILE* aFile, const char* aPrefix) {} void LayerManager::Log(const char* aPrefix) {} void LayerManager::LogSelf(const char* aPrefix) {} diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 73f517b05ee0..484f9462d5e0 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -419,7 +419,7 @@ public: * Dump information about this layer manager and its managed tree to * aFile, which defaults to stderr. */ - void Dump(FILE* aFile=NULL, const char* aPrefix=""); + void Dump(FILE* aFile=NULL, const char* aPrefix="", bool aDumpHtml=false); /** * Dump information about just this layer manager itself to aFile, * which defaults to stderr. @@ -880,7 +880,7 @@ public: * Dump information about this layer manager and its managed tree to * aFile, which defaults to stderr. */ - void Dump(FILE* aFile=NULL, const char* aPrefix=""); + void Dump(FILE* aFile=NULL, const char* aPrefix="", bool aDumpHtml=false); /** * Dump information about just this layer manager itself to aFile, * which defaults to stderr. diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp index 857e6531a0bc..3401dd8d18b1 100644 --- a/layout/base/FrameLayerBuilder.cpp +++ b/layout/base/FrameLayerBuilder.cpp @@ -2827,9 +2827,9 @@ FrameLayerBuilder::CheckDOMModified() #ifdef MOZ_DUMP_PAINTING /* static */ void -FrameLayerBuilder::DumpRetainedLayerTree(LayerManager* aManager, FILE* aFile) +FrameLayerBuilder::DumpRetainedLayerTree(LayerManager* aManager, FILE* aFile, bool aDumpHtml) { - aManager->Dump(aFile); + aManager->Dump(aFile, "", aDumpHtml); } #endif diff --git a/layout/base/FrameLayerBuilder.h b/layout/base/FrameLayerBuilder.h index 1db19504e941..eccda223b1a4 100644 --- a/layout/base/FrameLayerBuilder.h +++ b/layout/base/FrameLayerBuilder.h @@ -285,9 +285,9 @@ public: #ifdef MOZ_DUMP_PAINTING /** * Dumps this FrameLayerBuilder's retained layer manager's retained - * layer tree to stderr. + * layer tree. Defaults to dumping to stdout in non-HTML format. */ - static void DumpRetainedLayerTree(LayerManager* aManager, FILE* aFile = stdout); + static void DumpRetainedLayerTree(LayerManager* aManager, FILE* aFile = stdout, bool aDumpHtml = false); #endif /******* PRIVATE METHODS to FrameLayerBuilder.cpp ********/ diff --git a/layout/base/nsLayoutDebugger.cpp b/layout/base/nsLayoutDebugger.cpp index fefd1e3df7b4..e41a74ffaae7 100644 --- a/layout/base/nsLayoutDebugger.cpp +++ b/layout/base/nsLayoutDebugger.cpp @@ -119,18 +119,26 @@ nsLayoutDebugger::GetStyleSize(nsIPresShell* aPresentation, #endif #ifdef MOZ_DUMP_PAINTING +static int sPrintDisplayListIndent = 0; + static void PrintDisplayListTo(nsDisplayListBuilder* aBuilder, const nsDisplayList& aList, - FILE* aOutput) + FILE* aOutput, bool aDumpHtml) { - fprintf(aOutput, "
      "); + if (aDumpHtml) { + fprintf(aOutput, "
        "); + } for (nsDisplayItem* i = aList.GetBottom(); i != nullptr; i = i->GetAbove()) { #ifdef DEBUG if (aList.DidComputeVisibility() && i->GetVisibleRect().IsEmpty()) continue; #endif - fprintf(aOutput, "
      • "); + if (aDumpHtml) { + fprintf(aOutput, "
      • "); + } else { + sPrintDisplayListIndent ++; + } nsIFrame* f = i->GetUnderlyingFrame(); nsAutoString fName; #ifdef DEBUG @@ -164,7 +172,7 @@ PrintDisplayListTo(nsDisplayListBuilder* aBuilder, const nsDisplayList& aList, opaque = i->GetOpaqueRegion(aBuilder, &snap); } #endif - if (i->Painted()) { + if (aDumpHtml && i->Painted()) { nsCString string(i->Name()); string.Append("-"); string.AppendInt((PRUint64)i); @@ -179,15 +187,19 @@ PrintDisplayListTo(nsDisplayListBuilder* aBuilder, const nsDisplayList& aList, nsRegionRectIterator iter(opaque); for (const nsRect* r = iter.Next(); r; r = iter.Next()) { printf("(opaque %d,%d,%d,%d)", r->x, r->y, r->width, r->height); - } - if (i->Painted()) { + } + if (aDumpHtml && i->Painted()) { fprintf(aOutput, ""); } if (f) { PRUint32 key = i->GetPerFrameKey(); Layer* layer = mozilla::FrameLayerBuilder::GetDebugOldLayerFor(f, key); if (layer) { - fprintf(aOutput, " layer=%p", layer, layer); + if (aDumpHtml) { + fprintf(aOutput, " layer=%p", layer, layer); + } else { + fprintf(aOutput, " layer=%p", layer); + } } } if (i->GetType() == nsDisplayItem::TYPE_SVG_EFFECTS) { @@ -195,20 +207,27 @@ PrintDisplayListTo(nsDisplayListBuilder* aBuilder, const nsDisplayList& aList, } fputc('\n', aOutput); if (list) { - PrintDisplayListTo(aBuilder, *list, aOutput); + PrintDisplayListTo(aBuilder, *list, aOutput, aDumpHtml); + } + if (aDumpHtml) { + fprintf(aOutput, "
      • "); + } else { + sPrintDisplayListIndent --; } - fprintf(aOutput, ""); } - - fprintf(aOutput, "
      "); + + if (aDumpHtml) { + fprintf(aOutput, "
    "); + } } void nsFrame::PrintDisplayList(nsDisplayListBuilder* aBuilder, const nsDisplayList& aList, - FILE* aFile) + FILE* aFile, + bool aDumpHtml) { - PrintDisplayListTo(aBuilder, aList, aFile); + PrintDisplayListTo(aBuilder, aList, aFile, aDumpHtml); } #endif diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index e5e76f7f4f92..81b2f6d39def 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -1819,10 +1819,12 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram } else { gfxUtils::sDumpPaintFile = stdout; } - fprintf(gfxUtils::sDumpPaintFile, ""); + if (gfxUtils::sDumpPaintingToFile) { + fprintf(gfxUtils::sDumpPaintFile, ""); + } fprintf(gfxUtils::sDumpPaintFile, "Painting --- before optimization (dirty %d,%d,%d,%d):\n", dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height); - nsFrame::PrintDisplayList(&builder, list, gfxUtils::sDumpPaintFile); + nsFrame::PrintDisplayList(&builder, list, gfxUtils::sDumpPaintFile, gfxUtils::sDumpPaintingToFile); if (gfxUtils::sDumpPaintingToFile) { fprintf(gfxUtils::sDumpPaintFile, "Painting --- after optimization:\n"); - nsFrame::PrintDisplayList(&builder, list, gfxUtils::sDumpPaintFile); + if (gfxUtils::sDumpPaintingToFile) { + fprintf(gfxUtils::sDumpPaintFile, ""); + } + fprintf(gfxUtils::sDumpPaintFile, "Painting --- after optimization:\n"); + nsFrame::PrintDisplayList(&builder, list, gfxUtils::sDumpPaintFile, gfxUtils::sDumpPaintingToFile); fprintf(gfxUtils::sDumpPaintFile, "Painting --- retained layer tree:\n"); nsIWidget* widget = aFrame->GetNearestWidget(); if (widget) { nsRefPtr layerManager = widget->GetLayerManager(); if (layerManager) { - FrameLayerBuilder::DumpRetainedLayerTree(layerManager, gfxUtils::sDumpPaintFile); + FrameLayerBuilder::DumpRetainedLayerTree(layerManager, gfxUtils::sDumpPaintFile, + gfxUtils::sDumpPaintingToFile); } } - fprintf(gfxUtils::sDumpPaintFile, ""); - if (gfxUtils::sDumpPaintingToFile) { + fprintf(gfxUtils::sDumpPaintFile, ""); fclose(gfxUtils::sDumpPaintFile); } gfxUtils::sDumpPaintFile = NULL; diff --git a/layout/generic/nsFrame.h b/layout/generic/nsFrame.h index 170e2025c5d4..791dfb580ed9 100644 --- a/layout/generic/nsFrame.h +++ b/layout/generic/nsFrame.h @@ -707,7 +707,8 @@ public: static void PrintDisplayList(nsDisplayListBuilder* aBuilder, const nsDisplayList& aList, - FILE* aFile = stdout); + FILE* aFile = stdout, + bool aDumpHtml = false); #endif }; From 773302a74ce56771894971df54a3749995b62549 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Tue, 7 Aug 2012 14:25:26 -0400 Subject: [PATCH 041/169] Bug 779288 - Set CCACHE_CPP2 on linux too. r=khuey. move the definition out of a OS X only block. --- config/config.mk | 11 +++++------ js/src/config/config.mk | 11 +++++------ 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/config/config.mk b/config/config.mk index e361689fcf12..be36ec9df03e 100644 --- a/config/config.mk +++ b/config/config.mk @@ -562,12 +562,6 @@ export MACOSX_DEPLOYMENT_TARGET PBBUILD_SETTINGS += MACOSX_DEPLOYMENT_TARGET="$(MACOSX_DEPLOYMENT_TARGET)" endif # MACOSX_DEPLOYMENT_TARGET -ifdef MOZ_USING_CCACHE -ifdef CLANG_CXX -export CCACHE_CPP2=1 -endif -endif - ifdef MOZ_OPTIMIZE ifeq (2,$(MOZ_OPTIMIZE)) # Only override project defaults if the config specified explicit settings @@ -576,6 +570,11 @@ endif # MOZ_OPTIMIZE=2 endif # MOZ_OPTIMIZE endif # OS_ARCH=Darwin +ifdef MOZ_USING_CCACHE +ifdef CLANG_CXX +export CCACHE_CPP2=1 +endif +endif ifdef MOZ_NATIVE_MAKEDEPEND MKDEPEND_DIR = diff --git a/js/src/config/config.mk b/js/src/config/config.mk index e361689fcf12..be36ec9df03e 100644 --- a/js/src/config/config.mk +++ b/js/src/config/config.mk @@ -562,12 +562,6 @@ export MACOSX_DEPLOYMENT_TARGET PBBUILD_SETTINGS += MACOSX_DEPLOYMENT_TARGET="$(MACOSX_DEPLOYMENT_TARGET)" endif # MACOSX_DEPLOYMENT_TARGET -ifdef MOZ_USING_CCACHE -ifdef CLANG_CXX -export CCACHE_CPP2=1 -endif -endif - ifdef MOZ_OPTIMIZE ifeq (2,$(MOZ_OPTIMIZE)) # Only override project defaults if the config specified explicit settings @@ -576,6 +570,11 @@ endif # MOZ_OPTIMIZE=2 endif # MOZ_OPTIMIZE endif # OS_ARCH=Darwin +ifdef MOZ_USING_CCACHE +ifdef CLANG_CXX +export CCACHE_CPP2=1 +endif +endif ifdef MOZ_NATIVE_MAKEDEPEND MKDEPEND_DIR = From 58c508c1f3e66e2b74fc8b71657bf3ef083818a5 Mon Sep 17 00:00:00 2001 From: Timothy Nikkel Date: Tue, 7 Aug 2012 13:25:39 -0500 Subject: [PATCH 042/169] Add crashtests from bug 460389 and bug 522170. --- layout/base/crashtests/460389-1.html | 6 ++++++ layout/base/crashtests/crashtests.list | 1 + layout/generic/crashtests/522170-1.html | 1 + layout/generic/crashtests/crashtests.list | 1 + 4 files changed, 9 insertions(+) create mode 100644 layout/base/crashtests/460389-1.html create mode 100644 layout/generic/crashtests/522170-1.html diff --git a/layout/base/crashtests/460389-1.html b/layout/base/crashtests/460389-1.html new file mode 100644 index 000000000000..cee1803b0992 --- /dev/null +++ b/layout/base/crashtests/460389-1.html @@ -0,0 +1,6 @@ + + + +
    ۍ
    T
    + + diff --git a/layout/base/crashtests/crashtests.list b/layout/base/crashtests/crashtests.list index 59b5fc4fcf5c..8e53c4caf6e3 100644 --- a/layout/base/crashtests/crashtests.list +++ b/layout/base/crashtests/crashtests.list @@ -240,6 +240,7 @@ load 455063-3.html load 455171-4.html load 455623-1.html load 457362-1.xhtml +load 460389-1.html load 466763-1.html load 467881-1.html load 468491-1.html diff --git a/layout/generic/crashtests/522170-1.html b/layout/generic/crashtests/522170-1.html new file mode 100644 index 000000000000..7925c87bd9f1 --- /dev/null +++ b/layout/generic/crashtests/522170-1.html @@ -0,0 +1 @@ +
    diff --git a/layout/generic/crashtests/crashtests.list b/layout/generic/crashtests/crashtests.list index 4d3fa41bce20..c3df9040cb1c 100644 --- a/layout/generic/crashtests/crashtests.list +++ b/layout/generic/crashtests/crashtests.list @@ -313,6 +313,7 @@ load 515811-1.html load 517968.html load 519031.xhtml load 520340.html +load 522170-1.html load 533379-1.html load 533379-2.html load 534082-1.html From 817d05b030130756b269981310f0310143ae5caa Mon Sep 17 00:00:00 2001 From: Joey Armstrong Date: Tue, 7 Aug 2012 14:42:30 -0400 Subject: [PATCH 043/169] bug 771287: xpidl unit test failure --- config/makefiles/test/Makefile.in | 1 + config/makefiles/test/check-xpidl.mk | 5 +++++ config/makefiles/xpidl.mk | 2 ++ js/src/config/makefiles/xpidl.mk | 2 ++ 4 files changed, 10 insertions(+) diff --git a/config/makefiles/test/Makefile.in b/config/makefiles/test/Makefile.in index 7c521b4e7bde..56ad5b606e8d 100644 --- a/config/makefiles/test/Makefile.in +++ b/config/makefiles/test/Makefile.in @@ -128,6 +128,7 @@ $(check-export-targets): $(check-export-targets-preqs) ##{ check-xpidl-preqs=\ $(call mkdir_deps,$(dir-ts)) \ + $(topsrcdir)/config/config.mk \ $(topsrcdir)/config/makefiles/makeutils.mk \ $(topsrcdir)/config/makefiles/xpidl.mk \ $(srcdir)/check-xpidl.mk \ diff --git a/config/makefiles/test/check-xpidl.mk b/config/makefiles/test/check-xpidl.mk index 493a88520ee8..d02d06e30cce 100644 --- a/config/makefiles/test/check-xpidl.mk +++ b/config/makefiles/test/check-xpidl.mk @@ -8,6 +8,10 @@ ifdef VERBOSE $(warning loading test) endif +# Limit scope, we only need install_cmd= for testing +INCLUDED_AUTOCONF_MK = 1 +include $(topsrcdir)/config/config.mk + USE_AUTOTARGETS_MK = 1 include $(topsrcdir)/config/makefiles/makeutils.mk @@ -21,6 +25,7 @@ XPIDLSRCS = $(srcdir)/check-xpidl.mk include $(topsrcdir)/config/makefiles/xpidl.mk + $(call requiredfunction,topsrcdir) $(call requiredfunction,XPIDL_GEN_DIR) diff --git a/config/makefiles/xpidl.mk b/config/makefiles/xpidl.mk index ba10306e181a..ea9d36c8d12b 100644 --- a/config/makefiles/xpidl.mk +++ b/config/makefiles/xpidl.mk @@ -39,6 +39,8 @@ endif #} INCLUDED_XPIDL_MK ########################################################################### ifdef _xpidl-todo_ #{ +$(call requiredfunction,install_cmd) + ## Logic batch #1 xpidl-install-src-preqs=\ $(XPIDLSRCS) \ diff --git a/js/src/config/makefiles/xpidl.mk b/js/src/config/makefiles/xpidl.mk index ba10306e181a..ea9d36c8d12b 100644 --- a/js/src/config/makefiles/xpidl.mk +++ b/js/src/config/makefiles/xpidl.mk @@ -39,6 +39,8 @@ endif #} INCLUDED_XPIDL_MK ########################################################################### ifdef _xpidl-todo_ #{ +$(call requiredfunction,install_cmd) + ## Logic batch #1 xpidl-install-src-preqs=\ $(XPIDLSRCS) \ From ad6b36600aea08cf4e77c57c04e4faf9ce28ef9f Mon Sep 17 00:00:00 2001 From: Chris Peterson Date: Thu, 2 Aug 2012 17:13:40 -0700 Subject: [PATCH 044/169] Bug 778468 - Part 7: Move GeckoEventListener to org.mozilla.gecko.util package. r=blassey --HG-- extra : rebase_source : d0b2982b64126c046c5c974c7ec014992bef63b7 --- build/mobile/robocop/FennecNativeActions.java.in | 2 +- build/mobile/robocop/FennecNativeDriver.java.in | 2 +- mobile/android/base/DoorHangerPopup.java | 2 ++ mobile/android/base/FormAssistPopup.java | 1 + mobile/android/base/GeckoApp.java | 1 + mobile/android/base/GeckoAppShell.java | 2 ++ mobile/android/base/GeckoEventListener.java | 6 +++--- mobile/android/base/GeckoEventResponder.java | 4 ++-- mobile/android/base/GeckoPreferences.java | 2 ++ mobile/android/base/Makefile.in | 4 ++-- mobile/android/base/ProfileMigrator.java | 1 + mobile/android/base/PromptService.java | 1 + mobile/android/base/Tabs.java | 1 + mobile/android/base/TextSelection.java | 1 + mobile/android/base/awesomebar/AllPagesTab.java | 1 + mobile/android/base/db/FormHistoryProvider.java.in | 2 +- mobile/android/base/db/GeckoProvider.java.in | 2 +- mobile/android/base/db/PasswordsProvider.java.in | 2 +- mobile/android/base/gfx/GeckoLayerClient.java | 2 +- mobile/android/base/ui/PanZoomController.java | 2 +- mobile/android/base/ui/SubdocumentScrollHelper.java | 2 +- 21 files changed, 28 insertions(+), 15 deletions(-) diff --git a/build/mobile/robocop/FennecNativeActions.java.in b/build/mobile/robocop/FennecNativeActions.java.in index cf5a68701a3b..39075078521b 100644 --- a/build/mobile/robocop/FennecNativeActions.java.in +++ b/build/mobile/robocop/FennecNativeActions.java.in @@ -59,7 +59,7 @@ public class FennecNativeActions implements Actions { // Set up reflexive access of java classes and methods. try { mClassLoader = activity.getClassLoader(); - mGel = mClassLoader.loadClass("org.mozilla.gecko.GeckoEventListener"); + mGel = mClassLoader.loadClass("org.mozilla.gecko.util.GeckoEventListener"); mGe = mClassLoader.loadClass("org.mozilla.gecko.GeckoEvent"); mGas = mClassLoader.loadClass("org.mozilla.gecko.GeckoAppShell"); Class [] parameters = new Class[2]; diff --git a/build/mobile/robocop/FennecNativeDriver.java.in b/build/mobile/robocop/FennecNativeDriver.java.in index 44395ea618b7..5262284cc27d 100644 --- a/build/mobile/robocop/FennecNativeDriver.java.in +++ b/build/mobile/robocop/FennecNativeDriver.java.in @@ -88,7 +88,7 @@ public class FennecNativeDriver implements Driver { // Set up reflexive access of java classes and methods. try { mClassLoader = activity.getClassLoader(); - mGel = mClassLoader.loadClass("org.mozilla.gecko.GeckoEventListener"); + mGel = mClassLoader.loadClass("org.mozilla.gecko.util.GeckoEventListener"); mGe = mClassLoader.loadClass("org.mozilla.gecko.GeckoEvent"); mGas = mClassLoader.loadClass("org.mozilla.gecko.GeckoAppShell"); Class [] parameters = new Class[2]; diff --git a/mobile/android/base/DoorHangerPopup.java b/mobile/android/base/DoorHangerPopup.java index 662f82942364..02cf35b1a8b9 100644 --- a/mobile/android/base/DoorHangerPopup.java +++ b/mobile/android/base/DoorHangerPopup.java @@ -5,6 +5,8 @@ package org.mozilla.gecko; +import org.mozilla.gecko.util.GeckoEventListener; + import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; diff --git a/mobile/android/base/FormAssistPopup.java b/mobile/android/base/FormAssistPopup.java index 26cc76ff117e..9f678a6bb65b 100644 --- a/mobile/android/base/FormAssistPopup.java +++ b/mobile/android/base/FormAssistPopup.java @@ -6,6 +6,7 @@ package org.mozilla.gecko; import org.mozilla.gecko.gfx.FloatSize; +import org.mozilla.gecko.util.GeckoEventListener; import org.json.JSONArray; import org.json.JSONException; diff --git a/mobile/android/base/GeckoApp.java b/mobile/android/base/GeckoApp.java index d0d3ecbf733c..28a43f1b3b6a 100644 --- a/mobile/android/base/GeckoApp.java +++ b/mobile/android/base/GeckoApp.java @@ -13,6 +13,7 @@ import org.mozilla.gecko.gfx.PluginLayer; import org.mozilla.gecko.gfx.PointUtils; import org.mozilla.gecko.ui.PanZoomController; import org.mozilla.gecko.util.GeckoAsyncTask; +import org.mozilla.gecko.util.GeckoEventListener; import org.json.JSONArray; import org.json.JSONException; diff --git a/mobile/android/base/GeckoAppShell.java b/mobile/android/base/GeckoAppShell.java index 37da54de8587..a1bc111ae2bd 100644 --- a/mobile/android/base/GeckoAppShell.java +++ b/mobile/android/base/GeckoAppShell.java @@ -16,6 +16,8 @@ import org.mozilla.gecko.gfx.ScreenshotLayer; import org.mozilla.gecko.mozglue.DirectBufferAllocator; import org.mozilla.gecko.util.FloatUtils; import org.mozilla.gecko.util.GeckoBackgroundThread; +import org.mozilla.gecko.util.GeckoEventListener; +import org.mozilla.gecko.util.GeckoEventResponder; import org.json.JSONObject; diff --git a/mobile/android/base/GeckoEventListener.java b/mobile/android/base/GeckoEventListener.java index 681bde28b1b2..ba37f0541a17 100644 --- a/mobile/android/base/GeckoEventListener.java +++ b/mobile/android/base/GeckoEventListener.java @@ -3,13 +3,13 @@ * 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/. */ -package org.mozilla.gecko; +package org.mozilla.gecko.util; import org.json.JSONObject; /* This class is referenced by Robocop via reflection; use care when * modifying the signature. - */ + */ public interface GeckoEventListener { - public void handleMessage(String event, JSONObject message); + void handleMessage(String event, JSONObject message); } diff --git a/mobile/android/base/GeckoEventResponder.java b/mobile/android/base/GeckoEventResponder.java index 3121052cbdf9..3ce41f50030c 100644 --- a/mobile/android/base/GeckoEventResponder.java +++ b/mobile/android/base/GeckoEventResponder.java @@ -7,8 +7,8 @@ * * ***** END LICENSE BLOCK ***** */ -package org.mozilla.gecko; +package org.mozilla.gecko.util; public interface GeckoEventResponder extends GeckoEventListener { - public String getResponse(); + String getResponse(); } diff --git a/mobile/android/base/GeckoPreferences.java b/mobile/android/base/GeckoPreferences.java index 0cd5cad93b41..cff9b620535c 100644 --- a/mobile/android/base/GeckoPreferences.java +++ b/mobile/android/base/GeckoPreferences.java @@ -5,6 +5,8 @@ package org.mozilla.gecko; +import org.mozilla.gecko.util.GeckoEventListener; + import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; diff --git a/mobile/android/base/Makefile.in b/mobile/android/base/Makefile.in index 04389e20f562..73cbc2938562 100644 --- a/mobile/android/base/Makefile.in +++ b/mobile/android/base/Makefile.in @@ -25,6 +25,8 @@ UTIL_JAVA_FILES := \ ActivityResultHandlerMap.java \ GeckoAsyncTask.java \ GeckoBackgroundThread.java \ + GeckoEventListener.java \ + GeckoEventResponder.java \ GeckoJarReader.java \ INIParser.java \ INISection.java \ @@ -69,8 +71,6 @@ FENNEC_JAVA_FILES = \ GeckoBatteryManager.java \ GeckoConnectivityReceiver.java \ GeckoEvent.java \ - GeckoEventListener.java \ - GeckoEventResponder.java \ GeckoHalDefines.java \ GeckoInputConnection.java \ GeckoMenu.java \ diff --git a/mobile/android/base/ProfileMigrator.java b/mobile/android/base/ProfileMigrator.java index 075ce7663d96..8c12c29c96c7 100644 --- a/mobile/android/base/ProfileMigrator.java +++ b/mobile/android/base/ProfileMigrator.java @@ -13,6 +13,7 @@ import org.mozilla.gecko.sqlite.SQLiteBridge; import org.mozilla.gecko.sqlite.SQLiteBridgeException; import org.mozilla.gecko.sync.setup.SyncAccounts; import org.mozilla.gecko.sync.setup.SyncAccounts.SyncAccountParameters; +import org.mozilla.gecko.util.GeckoEventListener; import org.json.JSONArray; import org.json.JSONException; diff --git a/mobile/android/base/PromptService.java b/mobile/android/base/PromptService.java index 31b7a51dd8c8..bd595b24cf87 100644 --- a/mobile/android/base/PromptService.java +++ b/mobile/android/base/PromptService.java @@ -6,6 +6,7 @@ package org.mozilla.gecko; import org.mozilla.gecko.gfx.GeckoLayerClient; +import org.mozilla.gecko.util.GeckoEventResponder; import org.json.JSONArray; import org.json.JSONObject; diff --git a/mobile/android/base/Tabs.java b/mobile/android/base/Tabs.java index 0d508f1cd8f8..038a9f3dcd96 100644 --- a/mobile/android/base/Tabs.java +++ b/mobile/android/base/Tabs.java @@ -6,6 +6,7 @@ package org.mozilla.gecko; import org.mozilla.gecko.db.BrowserDB; +import org.mozilla.gecko.util.GeckoEventListener; import org.json.JSONException; import org.json.JSONObject; diff --git a/mobile/android/base/TextSelection.java b/mobile/android/base/TextSelection.java index 6628945a1f02..a88de455ba40 100644 --- a/mobile/android/base/TextSelection.java +++ b/mobile/android/base/TextSelection.java @@ -8,6 +8,7 @@ import org.mozilla.gecko.gfx.GeckoLayerClient; import org.mozilla.gecko.gfx.Layer; import org.mozilla.gecko.gfx.Layer.RenderContext; import org.mozilla.gecko.util.FloatUtils; +import org.mozilla.gecko.util.GeckoEventListener; import org.json.JSONObject; diff --git a/mobile/android/base/awesomebar/AllPagesTab.java b/mobile/android/base/awesomebar/AllPagesTab.java index cbb0320559cc..f8d90e937c98 100644 --- a/mobile/android/base/awesomebar/AllPagesTab.java +++ b/mobile/android/base/awesomebar/AllPagesTab.java @@ -9,6 +9,7 @@ import org.mozilla.gecko.AwesomeBar.ContextMenuSubject; import org.mozilla.gecko.db.BrowserContract.Combined; import org.mozilla.gecko.db.BrowserDB; import org.mozilla.gecko.db.BrowserDB.URLColumns; +import org.mozilla.gecko.util.GeckoEventListener; import org.json.JSONArray; import org.json.JSONException; diff --git a/mobile/android/base/db/FormHistoryProvider.java.in b/mobile/android/base/db/FormHistoryProvider.java.in index d58beb6e6e34..7abf23a9fd3b 100644 --- a/mobile/android/base/db/FormHistoryProvider.java.in +++ b/mobile/android/base/db/FormHistoryProvider.java.in @@ -16,7 +16,7 @@ import org.mozilla.gecko.GeckoApp; import org.mozilla.gecko.GeckoAppShell; import org.mozilla.gecko.GeckoProfile; import org.mozilla.gecko.GeckoEvent; -import org.mozilla.gecko.GeckoEventListener; +import org.mozilla.gecko.util.GeckoEventListener; import org.mozilla.gecko.db.BrowserContract.CommonColumns; import org.mozilla.gecko.db.DBUtils; import org.mozilla.gecko.db.BrowserContract.FormHistory; diff --git a/mobile/android/base/db/GeckoProvider.java.in b/mobile/android/base/db/GeckoProvider.java.in index f33299034123..2bc8a9ebfc0d 100644 --- a/mobile/android/base/db/GeckoProvider.java.in +++ b/mobile/android/base/db/GeckoProvider.java.in @@ -18,7 +18,6 @@ import org.mozilla.gecko.GeckoApp; import org.mozilla.gecko.GeckoAppShell; import org.mozilla.gecko.GeckoProfile; import org.mozilla.gecko.GeckoEvent; -import org.mozilla.gecko.GeckoEventListener; import org.mozilla.gecko.db.BrowserContract.CommonColumns; import org.mozilla.gecko.db.DBUtils; import org.mozilla.gecko.db.BrowserContract.Passwords; @@ -28,6 +27,7 @@ import org.mozilla.gecko.db.BrowserContract; import org.mozilla.gecko.sqlite.SQLiteBridge; import org.mozilla.gecko.sqlite.SQLiteBridgeException; import org.mozilla.gecko.sync.Utils; +import org.mozilla.gecko.util.GeckoEventListener; import android.content.ContentProvider; import android.content.ContentUris; diff --git a/mobile/android/base/db/PasswordsProvider.java.in b/mobile/android/base/db/PasswordsProvider.java.in index 5f9e9e12d4e0..1a7d67208470 100644 --- a/mobile/android/base/db/PasswordsProvider.java.in +++ b/mobile/android/base/db/PasswordsProvider.java.in @@ -15,7 +15,6 @@ import java.util.Random; import org.mozilla.gecko.GeckoApp; import org.mozilla.gecko.GeckoAppShell; import org.mozilla.gecko.GeckoEvent; -import org.mozilla.gecko.GeckoEventListener; import org.mozilla.gecko.GeckoProfile; import org.mozilla.gecko.NSSBridge; import org.mozilla.gecko.db.DBUtils; @@ -27,6 +26,7 @@ import org.mozilla.gecko.sqlite.MatrixBlobCursor; import org.mozilla.gecko.sqlite.SQLiteBridge; import org.mozilla.gecko.sqlite.SQLiteBridgeException; import org.mozilla.gecko.sync.Utils; +import org.mozilla.gecko.util.GeckoEventListener; import android.content.ContentProvider; import android.content.ContentUris; diff --git a/mobile/android/base/gfx/GeckoLayerClient.java b/mobile/android/base/gfx/GeckoLayerClient.java index ae0e522955ba..d6d72e9e6938 100644 --- a/mobile/android/base/gfx/GeckoLayerClient.java +++ b/mobile/android/base/gfx/GeckoLayerClient.java @@ -7,9 +7,9 @@ package org.mozilla.gecko.gfx; import org.mozilla.gecko.GeckoAppShell; import org.mozilla.gecko.GeckoEvent; -import org.mozilla.gecko.GeckoEventResponder; import org.mozilla.gecko.Tab; import org.mozilla.gecko.Tabs; +import org.mozilla.gecko.util.GeckoEventResponder; import org.mozilla.gecko.ZoomConstraints; import org.mozilla.gecko.ui.PanZoomController; import org.mozilla.gecko.ui.PanZoomTarget; diff --git a/mobile/android/base/ui/PanZoomController.java b/mobile/android/base/ui/PanZoomController.java index 5c8ad0bb0dd1..bf269e9dfcbf 100644 --- a/mobile/android/base/ui/PanZoomController.java +++ b/mobile/android/base/ui/PanZoomController.java @@ -8,12 +8,12 @@ package org.mozilla.gecko.ui; import org.mozilla.gecko.GeckoApp; import org.mozilla.gecko.GeckoAppShell; import org.mozilla.gecko.GeckoEvent; -import org.mozilla.gecko.GeckoEventListener; import org.mozilla.gecko.ZoomConstraints; import org.mozilla.gecko.gfx.ImmutableViewportMetrics; import org.mozilla.gecko.gfx.PointUtils; import org.mozilla.gecko.gfx.ViewportMetrics; import org.mozilla.gecko.util.FloatUtils; +import org.mozilla.gecko.util.GeckoEventListener; import org.json.JSONArray; import org.json.JSONException; diff --git a/mobile/android/base/ui/SubdocumentScrollHelper.java b/mobile/android/base/ui/SubdocumentScrollHelper.java index 66bca2527aeb..039136be43e0 100644 --- a/mobile/android/base/ui/SubdocumentScrollHelper.java +++ b/mobile/android/base/ui/SubdocumentScrollHelper.java @@ -7,7 +7,7 @@ package org.mozilla.gecko.ui; import org.mozilla.gecko.GeckoAppShell; import org.mozilla.gecko.GeckoEvent; -import org.mozilla.gecko.GeckoEventListener; +import org.mozilla.gecko.util.GeckoEventListener; import org.json.JSONException; import org.json.JSONObject; From 056dbff7ae50755ef0995ce6034b06c38960c465 Mon Sep 17 00:00:00 2001 From: Paul Dagnelie Date: Tue, 7 Aug 2012 12:07:27 -0700 Subject: [PATCH 045/169] Bug 759416 - XPCOM FileWatcherService. Interface change only. Patch to previous interface changes. sr=bsmedberg --- xpcom/io/nsIFile.idl | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/xpcom/io/nsIFile.idl b/xpcom/io/nsIFile.idl index 3841bd7b3cd5..807de374c69b 100644 --- a/xpcom/io/nsIFile.idl +++ b/xpcom/io/nsIFile.idl @@ -465,10 +465,8 @@ interface nsIFile : nsISupports * The listener to call out to when the file updates. * Updated will be recieved on the main thread. * - * @return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST if the file - * doesn't exist, NS_NOT_AVAILABLE if there is an - * out-of-memory or other resource failure, NS_OK - * otherwise. + * @return NS_NOT_AVAILABLE if there is an out-of-memory or other + * resource failure, NS_OK otherwise. */ void watch(in nsIFileUpdateListener listener); @@ -483,7 +481,7 @@ interface nsIFile : nsISupports * @param listener * the listener to stop calling out to * - * @return NS_ERROR_ILLEGAL_VALUE if the file is not being + * @return NS_NOT_AVAILABLE if the file is not being * watched with the given listener, NS_OK otherwise. */ void unwatch(in nsIFileUpdateListener listener); @@ -499,7 +497,7 @@ interface nsIFileUpdateListener : nsISupports * processed. * * @param type - * The type of update that occured (one of "created" "deleted" "modified" or "unknown"). + * The type of update that occured (one of "created" "deleted" or "modified"). * @param file * The file which has updated */ From 835c86f90b7d2caa3cd6751ed4ce096dc65ef27f Mon Sep 17 00:00:00 2001 From: Philipp von Weitershausen Date: Tue, 7 Aug 2012 12:11:48 -0700 Subject: [PATCH 046/169] Bug 777057 - MobileConnection: expose whether or not the radio is searching. r=marshall_law sr=sicking --- .../interfaces/nsIDOMMobileConnection.idl | 12 +- dom/network/tests/marionette/manifest.ini | 5 + .../tests/marionette/test_mobile_networks.js | 15 +- .../marionette/test_mobile_voice_state.js | 115 +++++++++++++++ dom/system/gonk/RILContentHelper.js | 1 + dom/system/gonk/RadioInterfaceLayer.js | 132 ++++++++---------- dom/system/gonk/ril_consts.js | 19 +++ dom/system/gonk/ril_worker.js | 123 ++++++++-------- 8 files changed, 280 insertions(+), 142 deletions(-) create mode 100644 dom/network/tests/marionette/test_mobile_voice_state.js diff --git a/dom/network/interfaces/nsIDOMMobileConnection.idl b/dom/network/interfaces/nsIDOMMobileConnection.idl index ef434cd85716..0c6706bb5b2c 100644 --- a/dom/network/interfaces/nsIDOMMobileConnection.idl +++ b/dom/network/interfaces/nsIDOMMobileConnection.idl @@ -222,11 +222,19 @@ interface nsIDOMMozMobileConnection : nsIDOMEventTarget attribute nsIDOMEventListener onussdreceived; }; -[scriptable, uuid(46321d6e-bbce-4b7b-aa32-d17b6aa984fe)] +[scriptable, uuid(6601c20e-337f-4286-8d6e-0990fc1c2372)] interface nsIDOMMozMobileConnectionInfo : nsISupports { /** - * Indicates whether the device is connected to a mobile network. + * State of the connection. + * + * Possible values: 'notSearching', 'searching', 'denied', 'registered'. + * null if the state is unknown. + */ + readonly attribute DOMString state; + + /** + * Indicates whether the connection is ready. This may be different */ readonly attribute bool connected; diff --git a/dom/network/tests/marionette/manifest.ini b/dom/network/tests/marionette/manifest.ini index 5233b793c448..3987271bfce9 100644 --- a/dom/network/tests/marionette/manifest.ini +++ b/dom/network/tests/marionette/manifest.ini @@ -3,3 +3,8 @@ b2g = true browser = false qemu = true + +[test_mobile_voice_state.js] +b2g = true +browser = false +qemu = true diff --git a/dom/network/tests/marionette/test_mobile_networks.js b/dom/network/tests/marionette/test_mobile_networks.js index 520c640e0d99..ce2573b0aa49 100644 --- a/dom/network/tests/marionette/test_mobile_networks.js +++ b/dom/network/tests/marionette/test_mobile_networks.js @@ -1,6 +1,5 @@ -/* 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/. */ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ // getNetworks() can take some time.. MARIONETTE_TIMEOUT = 60000; @@ -35,15 +34,17 @@ function isTelkilaNetwork(network) { function testConnectionInfo() { let voice = connection.voice; is(voice.connected, true); + is(voice.state, "registered"); is(voice.emergencyCallsOnly, false); is(voice.roaming, false); isAndroidNetwork(voice.network); let data = connection.data; - // TODO Bug 762959: enable these checks when data state updates are implemented - // is(data.connected, true); - // is(data.emergencyCallsOnly, false); - // is(data.roaming, false); + // data.connected = true means there's an active data call which we + // can't predict here. + is(data.state, "registered"); + is(data.emergencyCallsOnly, false); + is(data.roaming, false); isAndroidNetwork(data.network); testGetNetworks(); diff --git a/dom/network/tests/marionette/test_mobile_voice_state.js b/dom/network/tests/marionette/test_mobile_voice_state.js new file mode 100644 index 000000000000..134698c88507 --- /dev/null +++ b/dom/network/tests/marionette/test_mobile_voice_state.js @@ -0,0 +1,115 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +MARIONETTE_TIMEOUT = 30000; + +const WHITELIST_PREF = "dom.mobileconnection.whitelist"; +let uriPrePath = window.location.protocol + "//" + window.location.host; +SpecialPowers.setCharPref(WHITELIST_PREF, uriPrePath); + +let connection = navigator.mozMobileConnection; +ok(connection instanceof MozMobileConnection, + "connection is instanceof " + connection.constructor); + +function setEmulatorVoiceState(state) { + runEmulatorCmd("gsm voice " + state, function (result) { + is(result[0], "OK"); + }); +} + +function testConnectionInfo() { + let voice = connection.voice; + is(voice.connected, true); + is(voice.state, "registered"); + is(voice.emergencyCallsOnly, false); + is(voice.roaming, false); + + testUnregistered(); +} + +function testUnregistered() { + setEmulatorVoiceState("unregistered"); + + connection.addEventListener("voicechange", function onvoicechange() { + connection.removeEventListener("voicechange", onvoicechange); + + is(connection.voice.connected, false); + is(connection.voice.state, "notSearching"); + is(connection.voice.emergencyCallsOnly, false); + is(connection.voice.roaming, false); + + testSearching(); + }); +} + +function testSearching() { + // For some reason, requesting the "searching" state puts the fake modem + // into "registered"... Skipping this test for now. + testDenied(); + return; + + setEmulatorVoiceState("searching"); + + connection.addEventListener("voicechange", function onvoicechange() { + connection.removeEventListener("voicechange", onvoicechange); + + is(connection.voice.connected, false); + is(connection.voice.state, "searching"); + is(connection.voice.emergencyCallsOnly, false); + is(connection.voice.roaming, false); + + testDenied(); + }); +} + +function testDenied() { + setEmulatorVoiceState("denied"); + + connection.addEventListener("voicechange", function onvoicechange() { + connection.removeEventListener("voicechange", onvoicechange); + + is(connection.voice.connected, false); + is(connection.voice.state, "denied"); + is(connection.voice.emergencyCallsOnly, false); + is(connection.voice.roaming, false); + + testRoaming(); + }); +} + +function testRoaming() { + setEmulatorVoiceState("roaming"); + + connection.addEventListener("voicechange", function onvoicechange() { + connection.removeEventListener("voicechange", onvoicechange); + + is(connection.voice.connected, true); + is(connection.voice.state, "registered"); + is(connection.voice.emergencyCallsOnly, false); + is(connection.voice.roaming, true); + + testHome(); + }); +} + +function testHome() { + setEmulatorVoiceState("home"); + + connection.addEventListener("voicechange", function onvoicechange() { + connection.removeEventListener("voicechange", onvoicechange); + + is(connection.voice.connected, true); + is(connection.voice.state, "registered"); + is(connection.voice.emergencyCallsOnly, false); + is(connection.voice.roaming, false); + + cleanUp(); + }); +} + +function cleanUp() { + SpecialPowers.clearUserPref(WHITELIST_PREF); + finish(); +} + +testConnectionInfo(); diff --git a/dom/system/gonk/RILContentHelper.js b/dom/system/gonk/RILContentHelper.js index 18ca9ac8c545..32e2a3a1cfe3 100644 --- a/dom/system/gonk/RILContentHelper.js +++ b/dom/system/gonk/RILContentHelper.js @@ -85,6 +85,7 @@ MobileConnectionInfo.prototype = { // nsIDOMMozMobileConnectionInfo connected: false, + state: null, emergencyCallsOnly: false, roaming: false, network: null, diff --git a/dom/system/gonk/RadioInterfaceLayer.js b/dom/system/gonk/RadioInterfaceLayer.js index 68d98ce8f55a..4cee58a6f9bc 100644 --- a/dom/system/gonk/RadioInterfaceLayer.js +++ b/dom/system/gonk/RadioInterfaceLayer.js @@ -446,36 +446,32 @@ RadioInterfaceLayer.prototype = { let selectionMessage = message[RIL.NETWORK_INFO_NETWORK_SELECTION_MODE]; // Batch the *InfoChanged messages together - let voiceInfoChanged = false; if (voiceMessage) { voiceMessage.batch = true; - voiceInfoChanged = this.updateVoiceConnection(voiceMessage); + this.updateVoiceConnection(voiceMessage); } let dataInfoChanged = false; if (dataMessage) { dataMessage.batch = true; - dataInfoChanged = this.updateDataConnection(dataMessage); + this.updateDataConnection(dataMessage); } let voice = this.rilContext.voice; let data = this.rilContext.data; if (operatorMessage) { if (this.networkChanged(operatorMessage, voice.network)) { - voiceInfoChanged = true; voice.network = operatorMessage; } - if (this.networkChanged(operatorMessage, data.network)) { - dataInfoChanged = true; data.network = operatorMessage; } } - if (voiceInfoChanged) { + if (voiceMessage || operatorMessage) { ppmm.sendAsyncMessage("RIL:VoiceInfoChanged", voice); } - if (dataInfoChanged) { + if (dataMessage || operatorMessage) { ppmm.sendAsyncMessage("RIL:DataInfoChanged", data); } @@ -488,96 +484,88 @@ RadioInterfaceLayer.prototype = { * Sends the RIL:VoiceInfoChanged message when the voice * connection's state has changed. * - * @param state The new voice connection state. When state.batch is true, - * the RIL:VoiceInfoChanged message will not be sent. - * @return Whether or not this.radioState.voice was updated + * @param newInfo The new voice connection information. When newInfo.batch is true, + * the RIL:VoiceInfoChanged message will not be sent. */ - updateVoiceConnection: function updateVoiceConnection(state) { + updateVoiceConnection: function updateVoiceConnection(newInfo) { let voiceInfo = this.rilContext.voice; - let regState = state.regState; - voiceInfo.type = "gsm"; //TODO see bug 726098. - if (!state || regState == RIL.NETWORK_CREG_STATE_UNKNOWN) { - voiceInfo.connected = false; - voiceInfo.emergencyCallsOnly = false; - voiceInfo.roaming = false; + voiceInfo.state = newInfo.state; + voiceInfo.connected = newInfo.connected; + voiceInfo.roaming = newInfo.roaming; + voiceInfo.emergencyCallsOnly = newInfo.emergencyCallsOnly; + // Unlike the data registration info, the voice info typically contains + // no (useful) radio tech information, so we have to manually set + // this here. (TODO GSM only for now, see bug 726098.) + voiceInfo.type = "gsm"; + + // Make sure we also reset the operator and signal strength information + // if we drop off the network. + if (newInfo.regState == RIL.NETWORK_CREG_STATE_UNKNOWN) { voiceInfo.network = null; - voiceInfo.type = null; voiceInfo.signalStrength = null; voiceInfo.relSignalStrength = null; + } + + if (!newInfo.batch) { ppmm.sendAsyncMessage("RIL:VoiceInfoChanged", voiceInfo); - return false; } - - let isRoaming = regState == RIL.NETWORK_CREG_STATE_REGISTERED_ROAMING; - let isHome = regState == RIL.NETWORK_CREG_STATE_REGISTERED_HOME; - let isConnected = isRoaming || isHome; - let radioTech = RIL.GECKO_RADIO_TECH[state.radioTech] || null; - - // Ensure that we check for changes before sending the message - if (voiceInfo.emergencyCallsOnly != state.emergencyCallsOnly || - voiceInfo.connected != isConnected || - voiceInfo.roaming != isRoaming || - voiceInfo.type != radioTech) { - - voiceInfo.emergencyCallsOnly = state.emergencyCallsOnly; - voiceInfo.connected = isConnected; - voiceInfo.roaming = isRoaming; - voiceInfo.type = radioTech; - - // When batch is true, hold off on firing VoiceInfoChanged events - if (!state.batch) { - ppmm.sendAsyncMessage("RIL:VoiceInfoChanged", voiceInfo); - } - return true; - } - return false; }, - updateDataConnection: function updateDataConnection(state) { - let data = this.rilContext.data; - if (!state || state.regState == RIL.NETWORK_CREG_STATE_UNKNOWN) { - data.connected = false; - data.emergencyCallsOnly = false; - data.roaming = false; - data.network = null; - data.type = null; - data.signalStrength = null; - data.relSignalStrength = null; - ppmm.sendAsyncMessage("RIL:DataInfoChanged", data); - return false; + updateDataConnection: function updateDataConnection(newInfo) { + let dataInfo = this.rilContext.data; + dataInfo.state = newInfo.state; + dataInfo.roaming = newInfo.roaming; + dataInfo.emergencyCallsOnly = newInfo.emergencyCallsOnly; + dataInfo.type = newInfo.type; + // For the data connection, the `connected` flag indicates whether + // there's an active data call. + dataInfo.connected = RILNetworkInterface.connected; + + // Make sure we also reset the operator and signal strength information + // if we drop off the network. + if (newInfo.regState == RIL.NETWORK_CREG_STATE_UNKNOWN) { + dataInfo.network = null; + dataInfo.signalStrength = null; + dataInfo.relSignalStrength = null; + } + + if (!newInfo.batch) { + ppmm.sendAsyncMessage("RIL:DataInfoChanged", dataInfo); } - data.roaming = - (state.regState == RIL.NETWORK_CREG_STATE_REGISTERED_ROAMING); - data.type = RIL.GECKO_RADIO_TECH[state.radioTech] || null; - ppmm.sendAsyncMessage("RIL:DataInfoChanged", data); if (!this.dataCallSettings["enabled"]) { - return false; + return; } let isRegistered = - state.regState == RIL.NETWORK_CREG_STATE_REGISTERED_HOME || - (this.dataCallSettings["roaming_enabled"] && - state.regState == RIL.NETWORK_CREG_STATE_REGISTERED_ROAMING); + newInfo.state == RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED && + (!newInfo.roaming || this._isDataRoamingEnabled()); let haveDataConnection = - state.radioTech != RIL.NETWORK_CREG_TECH_UNKNOWN; + newInfo.type != GECKO_MOBILE_CONNECTION_STATE_UNKNOWN; if (isRegistered && haveDataConnection) { debug("Radio is ready for data connection."); this.updateRILNetworkInterface(); } - return false; }, handleSignalStrengthChange: function handleSignalStrengthChange(message) { + let voiceInfo = this.rilContext.voice; // TODO CDMA, EVDO, LTE, etc. (see bug 726098) - this.rilContext.voice.signalStrength = message.gsmDBM; - this.rilContext.voice.relSignalStrength = message.gsmRelative; - ppmm.sendAsyncMessage("RIL:VoiceInfoChanged", this.rilContext.voice); + if (voiceInfo.signalStrength != message.gsmDBM || + voiceInfo.relSignalStrength != message.gsmRelative) { + voiceInfo.signalStrength = message.gsmDBM; + voiceInfo.relSignalStrength = message.gsmRelative; + ppmm.sendAsyncMessage("RIL:VoiceInfoChanged", voiceInfo); + } - this.rilContext.data.signalStrength = message.gsmDBM; - this.rilContext.data.relSignalStrength = message.gsmRelative; - ppmm.sendAsyncMessage("RIL:DataInfoChanged", this.rilContext.data); + let dataInfo = this.rilContext.data; + if (dataInfo.signalStrength != message.gsmDBM || + dataInfo.relSignalStrength != message.gsmRelative) { + dataInfo.signalStrength = message.gsmDBM; + dataInfo.relSignalStrength = message.gsmRelative; + ppmm.sendAsyncMessage("RIL:DataInfoChanged", dataInfo); + } }, networkChanged: function networkChanged(srcNetwork, destNetwork) { diff --git a/dom/system/gonk/ril_consts.js b/dom/system/gonk/ril_consts.js index c5284f4fc7fe..65ddbd1937f0 100644 --- a/dom/system/gonk/ril_consts.js +++ b/dom/system/gonk/ril_consts.js @@ -1449,6 +1449,25 @@ const GECKO_NETWORK_SELECTION_UNKNOWN = null; const GECKO_NETWORK_SELECTION_AUTOMATIC = "automatic"; const GECKO_NETWORK_SELECTION_MANUAL = "manual"; +const GECKO_MOBILE_CONNECTION_STATE_UNKNOWN = null; +const GECKO_MOBILE_CONNECTION_STATE_NOTSEARCHING = "notSearching"; +const GECKO_MOBILE_CONNECTION_STATE_SEARCHING = "searching"; +const GECKO_MOBILE_CONNECTION_STATE_REGISTERED = "registered"; +const GECKO_MOBILE_CONNECTION_STATE_DENIED = "denied"; + +const NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE = {}; +NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_NOT_SEARCHING] = GECKO_MOBILE_CONNECTION_STATE_NOTSEARCHING; +NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_REGISTERED_HOME] = GECKO_MOBILE_CONNECTION_STATE_REGISTERED; +NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_SEARCHING] = GECKO_MOBILE_CONNECTION_STATE_REGISTERED; +NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_DENIED] = GECKO_MOBILE_CONNECTION_STATE_DENIED; +NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_UNKNOWN] = GECKO_MOBILE_CONNECTION_STATE_UNKNOWN; +NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_REGISTERED_ROAMING] = GECKO_MOBILE_CONNECTION_STATE_REGISTERED; +NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_NOT_SEARCHING_EMERGENCY_CALLS] = GECKO_MOBILE_CONNECTION_STATE_NOTSEARCHING; +NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_SEARCHING_EMERGENCY_CALLS] = GECKO_MOBILE_CONNECTION_STATE_SEARCHING; +NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_DENIED_EMERGENCY_CALLS] = GECKO_MOBILE_CONNECTION_STATE_DENIED; +NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[NETWORK_CREG_STATE_UNKNOWN_EMERGENCY_CALLS] = GECKO_MOBILE_CONNECTION_STATE_UNKNOWN; + + const GECKO_CALL_ERROR_BAD_NUMBER = "BadNumberError"; const GECKO_CALL_ERROR_NORMAL_CALL_CLEARING = "NormalCallClearingError"; const GECKO_CALL_ERROR_BUSY = "BusyError"; diff --git a/dom/system/gonk/ril_worker.js b/dom/system/gonk/ril_worker.js index d5a642e2a8c6..6351315d6986 100644 --- a/dom/system/gonk/ril_worker.js +++ b/dom/system/gonk/ril_worker.js @@ -62,6 +62,9 @@ let RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL = false; let RILQUIRKS_MODEM_DEFAULTS_TO_EMERGENCY_MODE = false; let RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS = false; +// Marker object. +let PENDING_NETWORK_TYPE = {}; + /** * This object contains helpers buffering incoming data & deconstructing it * into parcels as well as buffering outgoing data & constructing parcels. @@ -615,6 +618,8 @@ let RIL = { */ aid: null, + networkSelectionMode: null, + voiceRegistrationState: {}, dataRegistrationState: {}, @@ -1504,10 +1509,7 @@ let RIL = { */ requestNetworkInfo: function requestNetworkInfo() { if (this._processingNetworkInfo) { - if (DEBUG) { - debug("Already requesting network info: " + - JSON.stringify(this._pendingNetworkInfo)); - } + if (DEBUG) debug("Network info requested, but we're already requesting network info."); return; } @@ -2172,19 +2174,21 @@ let RIL = { return; } + if (DEBUG) debug("Queuing " + type + " network info message: " + JSON.stringify(message)); this._pendingNetworkInfo[type] = message; }, _receivedNetworkInfo: function _receivedNetworkInfo(type) { + if (DEBUG) debug("Received " + type + " network info."); if (!this._processingNetworkInfo) { return; } let pending = this._pendingNetworkInfo; - // We still need to track states for events that aren't fired + // We still need to track states for events that aren't fired. if (!(type in pending)) { - pending[type] = true; + pending[type] = PENDING_NETWORK_TYPE; } // Pending network info is ready to be sent when no more messages @@ -2192,58 +2196,77 @@ let RIL = { for (let i = 0; i < NETWORK_INFO_MESSAGE_TYPES.length; i++) { let type = NETWORK_INFO_MESSAGE_TYPES[i]; if (!(type in pending)) { + if (DEBUG) debug("Still missing some more network info, not notifying main thread."); return; } } // Do a pass to clean up the processed messages that didn't create // a response message, so we don't have unused keys in the outbound - // networkinfochanged message - let keys = Object.keys(pending); - for (let i = 0; i < keys.length; i++) { - let key = keys[i]; - if (pending[key] === true) { + // networkinfochanged message. + for (let key in pending) { + if (pending[key] == PENDING_NETWORK_TYPE) { delete pending[key]; } } + if (DEBUG) debug("All pending network info has been received: " + JSON.stringify(pending)); + // Send the message on the next tick of the worker's loop, so we give the // last message a chance to call _sendNetworkInfoMessage first. - setTimeout(this._sendPendingNetworkInfo.bind(this), 0); + setTimeout(this._sendPendingNetworkInfo, 0); }, _sendPendingNetworkInfo: function _sendPendingNetworkInfo() { - this.sendDOMMessage(this._pendingNetworkInfo); + RIL.sendDOMMessage(RIL._pendingNetworkInfo); - this._processingNetworkInfo = false; + RIL._processingNetworkInfo = false; for (let i = 0; i < NETWORK_INFO_MESSAGE_TYPES.length; i++) { - delete this._pendingNetworkInfo[NETWORK_INFO_MESSAGE_TYPES[i]]; + delete RIL._pendingNetworkInfo[NETWORK_INFO_MESSAGE_TYPES[i]]; } }, + /** + * Process the network registration flags. + * + * @return true if the state changed, false otherwise. + */ + _processCREG: function _processCREG(curState, newState) { + let changed = false; + + let regState = RIL.parseInt(newState[0], NETWORK_CREG_STATE_UNKNOWN); + if (curState.regState != regState) { + changed = true; + curState.regState = regState; + + curState.state = NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[regState]; + curState.connected = regState == NETWORK_CREG_STATE_REGISTERED_HOME || + regState == NETWORK_CREG_STATE_REGISTERED_ROAMING; + curState.roaming = regState == NETWORK_CREG_STATE_REGISTERED_ROAMING; + curState.emergencyCallsOnly = + (regState >= NETWORK_CREG_STATE_NOT_SEARCHING_EMERGENCY_CALLS) && + (regState <= NETWORK_CREG_STATE_UNKNOWN_EMERGENCY_CALLS); + if (RILQUIRKS_MODEM_DEFAULTS_TO_EMERGENCY_MODE) { + curState.emergencyCallsOnly = !curState.connected; + } + } + + let radioTech = RIL.parseInt(newState[3], NETWORK_CREG_TECH_UNKNOWN); + if (curState.radioTech != radioTech) { + changed = true; + curState.radioTech = radioTech; + curState.type = GECKO_RADIO_TECH[radioTech] || null; + } + return changed; + }, + _processVoiceRegistrationState: function _processVoiceRegistrationState(state) { this.initRILQuirks(); let rs = this.voiceRegistrationState; - let stateChanged = false; - - let regState = RIL.parseInt(state[0], NETWORK_CREG_STATE_UNKNOWN); - if (rs.regState != regState) { - rs.regState = regState; - if (RILQUIRKS_MODEM_DEFAULTS_TO_EMERGENCY_MODE) { - rs.emergencyCallsOnly = - (regState != NETWORK_CREG_STATE_REGISTERED_HOME) && - (regState != NETWORK_CREG_STATE_REGISTERED_ROAMING); - } else { - rs.emergencyCallsOnly = - (regState >= NETWORK_CREG_STATE_NOT_SEARCHING_EMERGENCY_CALLS) && - (regState <= NETWORK_CREG_STATE_UNKNOWN_EMERGENCY_CALLS); - } - stateChanged = true; - if (regState == NETWORK_CREG_STATE_REGISTERED_HOME || - regState == NETWORK_CREG_STATE_REGISTERED_ROAMING) { - RIL.getSMSCAddress(); - } + let stateChanged = this._processCREG(rs, state); + if (stateChanged && rs.connected) { + RIL.getSMSCAddress(); } let cell = this.cellLocation; @@ -2268,12 +2291,6 @@ let RIL = { this.sendDOMMessage(cell); } - let radioTech = RIL.parseInt(state[3], NETWORK_CREG_TECH_UNKNOWN); - if (rs.radioTech != radioTech) { - rs.radioTech = radioTech; - stateChanged = true; - } - // TODO: This zombie code branch that will be raised from the dead once // we add explicit CDMA support everywhere (bug 726098). let cdma = false; @@ -2301,20 +2318,7 @@ let RIL = { _processDataRegistrationState: function _processDataRegistrationState(state) { let rs = this.dataRegistrationState; - let stateChanged = false; - - let regState = RIL.parseInt(state[0], NETWORK_CREG_STATE_UNKNOWN); - if (rs.regState != regState) { - rs.regState = regState; - stateChanged = true; - } - - let radioTech = RIL.parseInt(state[3], NETWORK_CREG_TECH_UNKNOWN); - if (rs.radioTech != radioTech) { - rs.radioTech = radioTech; - stateChanged = true; - } - + let stateChanged = this._processCREG(rs, state); if (stateChanged) { rs.rilMessageType = "dataregistrationstatechange"; this._sendNetworkInfoMessage(NETWORK_INFO_DATA_REGISTRATION_STATE, rs); @@ -2333,7 +2337,7 @@ let RIL = { } let [longName, shortName, networkTuple] = operatorData; - let thisTuple = String(this.operator.mcc) + this.operator.mnc; + let thisTuple = "" + this.operator.mcc + this.operator.mnc; if (this.operator.longName !== longName || this.operator.shortName !== shortName || @@ -3180,11 +3184,8 @@ RIL[REQUEST_OPERATOR] = function REQUEST_OPERATOR(length, options) { } let operatorData = Buf.readStringList(); - if (DEBUG) debug("operator: " + operatorData); - + if (DEBUG) debug("Operator: " + operatorData); this._processOperator(operatorData); - - }; RIL[REQUEST_RADIO_POWER] = null; RIL[REQUEST_DTMF] = null; @@ -3383,8 +3384,8 @@ RIL[REQUEST_QUERY_NETWORK_SELECTION_MODE] = function REQUEST_QUERY_NETWORK_SELEC break; } - if (this.mode != selectionMode) { - this.mode = options.mode = selectionMode; + if (this.networkSelectionMode != selectionMode) { + this.networkSelectionMode = options.mode = selectionMode; options.rilMessageType = "networkselectionmodechange"; this._sendNetworkInfoMessage(NETWORK_INFO_NETWORK_SELECTION_MODE, options); } From 0e957e0c0697133e8d05073b9e42d0ccc885a5de Mon Sep 17 00:00:00 2001 From: Siddharth Agarwal Date: Wed, 8 Aug 2012 00:36:44 +0530 Subject: [PATCH 047/169] Bug 767833 - Pymake on Windows is busted with config/tests/makefiles/autodeps/check_mkdir.tpy. r=khuey Less MSYS, more Windows. --HG-- extra : rebase_source : cd26706f245c69667ec3afbd6c6a51527dd1592e --- config/tests/makefiles/autodeps/Makefile.in | 4 +- .../tests/makefiles/autodeps/check_mkdir.tpy | 60 +++++++++---------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/config/tests/makefiles/autodeps/Makefile.in b/config/tests/makefiles/autodeps/Makefile.in index bbe2f85228f7..d3f96fcbd02d 100644 --- a/config/tests/makefiles/autodeps/Makefile.in +++ b/config/tests/makefiles/autodeps/Makefile.in @@ -27,6 +27,8 @@ tgts =\ $(autotgt_tests) $(NULL) +export MAKE +export .PYMAKE ##------------------_## ##---] TARGETS [---## @@ -37,5 +39,5 @@ check:: $(tgts) # Only run unit test when autotargets.mk is modified $(autotgt_tests): $(topsrcdir)/config/makefiles/autotargets.mk - MAKECMD=$(MAKE) $(PYTEST) $(srcdir)/check_mkdir.tpy + $(PYTEST) $(srcdir)/check_mkdir.tpy @$(TOUCH) $@ diff --git a/config/tests/makefiles/autodeps/check_mkdir.tpy b/config/tests/makefiles/autodeps/check_mkdir.tpy index 7ab0cf1a1301..2b3f0d751e42 100644 --- a/config/tests/makefiles/autodeps/check_mkdir.tpy +++ b/config/tests/makefiles/autodeps/check_mkdir.tpy @@ -68,7 +68,7 @@ def path2posix(src): drive = '' winpath = src.find(':') if -1 != winpath and 10 > winpath: - (drive, tail) = src.split(':', 2) + (drive, tail) = src.split(':', 1) if drive: todo = [ '', drive.rstrip(':').lstrip('/').lstrip('\\') ] @@ -98,13 +98,19 @@ def checkMkdir(work, debug=False): logging.debug("Testing: checkMkdir") - if False: - path = os.path.abspath(__file__).split(os.sep) + # On Windows + Pymake, don't convert paths to POSIX + skipposix = sys.platform == "win32" and os.environ.get(".PYMAKE") == "1" + if skipposix: + path = os.path.abspath(__file__) + dirname_fun = os.path.dirname else: - path = path2posix(os.path.abspath(__file__)).split('/') - - root = os.path.join(os.sep, *path[:-5]) - src = os.path.join(os.sep, *path[:-1]) + path = path2posix(os.path.abspath(__file__)) + import posixpath + dirname_fun = posixpath.dirname + + src = dirname_fun(path) + # root is 5 directories up from path + root = reduce(lambda x, _: dirname_fun(x), xrange(5), path) rootP = path2posix(root) srcP = path2posix(src) @@ -114,37 +120,28 @@ def checkMkdir(work, debug=False): # [0] command paths use /c/foo # [1] os.path.exists() on mingw() requires C:\ paths = [ - [ # function generated - "%s/mkdir_bycall" % (workP), - "%s/mkdir_bycall" % (work), - ], - [ # explicit dependency - "%s/mkdir_bydep" % (workP), - "%s/mkdir_bydep" % (work), - ], - [ # by GENERATED_DIRS macro - "%s/mkdir_bygen" % (workP), - "%s/mkdir_bygen" % (work), - ] - ] + "mkdir_bycall", # function generated + "mkdir_bydep", # explicit dependency + "mkdir_bygen", # by GENERATED_DIRS macro + ] ## Use make from the parent "make check" call when available cmd = { 'make': 'make' } - shell0 = os.environ.get('MAKECMD') + shell0 = os.environ.get('MAKE') if shell0: shell = os.path.splitext(shell0)[0] # strip: .exe, .py if -1 != shell.find('make'): print "MAKE COMMAND FOUND: %s" % (shell0) - cmd['make'] = path2posix(shell0) + cmd['make'] = shell0 if skipposix else path2posix(shell0) args = [] args.append('%s' % (cmd['make'])) - args.append('-C %s' % (workP)) - args.append("-f %s/testor.tmpl" % (srcP)) - args.append('topsrcdir=%s' % (rootP)) - args.append('deps_mkdir_bycall=%s' % paths[0][0]) - args.append('deps_mkdir_bydep=%s' % paths[1][0]) - args.append('deps_mkdir_bygen=%s' % paths[2][0]) + args.append('-C %s' % (work if skipposix else workP)) + args.append("-f %s/testor.tmpl" % (src if skipposix else srcP)) + args.append('topsrcdir=%s' % (root if skipposix else rootP)) + args.append('deps_mkdir_bycall=%s' % paths[0]) + args.append('deps_mkdir_bydep=%s' % paths[1]) + args.append('deps_mkdir_bygen=%s' % paths[2]) args.append('checkup') # target # Call will fail on mingw with output redirected ?!? @@ -160,9 +157,10 @@ def checkMkdir(work, debug=False): raise Exception("make failed ($?=%s): cmd=%s" % (rc, cmd)) for i in paths: - logging.debug("Did testing mkdir(%s) succeed?" % (i[1])) - if not os.path.exists(i[1]): - raise Exception("Test path %s does not exist" % (i[1])) + path = os.path.join(work, i) + logging.debug("Did testing mkdir(%s) succeed?" % (path)) + if not os.path.exists(path): + raise Exception("Test path %s does not exist" % (path)) def parseargs(): From 71bbf89bc949491e9196b8ff7303caaaf67d2669 Mon Sep 17 00:00:00 2001 From: Siddharth Agarwal Date: Wed, 8 Aug 2012 00:38:48 +0530 Subject: [PATCH 048/169] Bug 741014 - Pymake is busted with make l10n-check. Hack around the spaces issue by using a wildcard, and fix an underspecified dependency. r=ted --HG-- extra : rebase_source : bbf2d6963f9eb2f2f3a3656fdd9833b719039717 --- browser/locales/Makefile.in | 7 ++++--- toolkit/locales/l10n.mk | 4 ++-- toolkit/mozapps/installer/packager.mk | 1 + 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/browser/locales/Makefile.in b/browser/locales/Makefile.in index f51c1abf5e72..4bb22f77dc54 100644 --- a/browser/locales/Makefile.in +++ b/browser/locales/Makefile.in @@ -154,9 +154,8 @@ libs-%: @$(MAKE) libs AB_CD=$* XPI_NAME=locale-$* PREF_DIR=$(PREF_DIR) BOTH_MANIFESTS=1 @$(MAKE) -C $(DEPTH)/$(MOZ_BRANDING_DIRECTORY)/locales AB_CD=$* XPI_NAME=locale-$* BOTH_MANIFESTS=1 - repackage-win32-installer: WIN32_INSTALLER_OUT=$(_ABS_DIST)/$(PKG_INST_PATH)$(PKG_INST_BASENAME).exe -repackage-win32-installer: $(call ESCAPE_SPACE,$(WIN32_INSTALLER_IN)) $(SUBMAKEFILES) libs-$(AB_CD) +repackage-win32-installer: $(call ESCAPE_WILDCARD,$(WIN32_INSTALLER_IN)) $(SUBMAKEFILES) libs-$(AB_CD) @echo "Repackaging $(WIN32_INSTALLER_IN) into $(WIN32_INSTALLER_OUT)." $(MAKE) -C $(DEPTH)/$(MOZ_BRANDING_DIRECTORY) export $(MAKE) -C ../installer/windows CONFIG_DIR=l10ngen l10ngen/setup.exe l10ngen/7zSD.sfx @@ -169,8 +168,10 @@ repackage-win32-installer: $(call ESCAPE_SPACE,$(WIN32_INSTALLER_IN)) $(SUBMAKEF $(topsrcdir)/browser/installer/windows/app.tag" ifeq (WINNT,$(OS_ARCH)) -repackage-win32-installer-%: +repackage-win32-installer-%: $(STAGEDIST) @$(MAKE) repackage-win32-installer AB_CD=$* WIN32_INSTALLER_IN="$(WIN32_INSTALLER_IN)" + +repackage-zip-%: repackage-win32-installer-% else repackage-win32-installer-%: ; endif diff --git a/toolkit/locales/l10n.mk b/toolkit/locales/l10n.mk index dc754d573323..af7e29e0ae12 100644 --- a/toolkit/locales/l10n.mk +++ b/toolkit/locales/l10n.mk @@ -77,8 +77,8 @@ include $(MOZILLA_DIR)/toolkit/mozapps/installer/packager.mk PACKAGE_BASE_DIR = $(_ABS_DIST)/l10n-stage $(STAGEDIST): AB_CD:=en-US -$(STAGEDIST): UNPACKAGE=$(call ESCAPE_SPACE,$(ZIP_IN)) -$(STAGEDIST): $(call ESCAPE_SPACE,$(ZIP_IN)) +$(STAGEDIST): UNPACKAGE=$(call ESCAPE_WILDCARD,$(ZIP_IN)) +$(STAGEDIST): $(call ESCAPE_WILDCARD,$(ZIP_IN)) # only mac needs to remove the parent of STAGEDIST... ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) $(RM) -r -v $(DIST)/l10n-stage diff --git a/toolkit/mozapps/installer/packager.mk b/toolkit/mozapps/installer/packager.mk index c01daf00bc20..bf06a8d8af76 100644 --- a/toolkit/mozapps/installer/packager.mk +++ b/toolkit/mozapps/installer/packager.mk @@ -972,6 +972,7 @@ empty := space = $(empty) $(empty) QUOTED_WILDCARD = $(if $(wildcard $(subst $(space),?,$(1))),"$(1)") ESCAPE_SPACE = $(subst $(space),\$(space),$(1)) +ESCAPE_WILDCARD = $(subst $(space),?,$(1)) # This variable defines which OpenSSL algorithm to use to # generate checksums for files that we upload From c8966962fadda6ceea2233badacef6804676e78d Mon Sep 17 00:00:00 2001 From: Siddharth Agarwal Date: Wed, 8 Aug 2012 00:49:02 +0530 Subject: [PATCH 049/169] Bug 780612 - Add a list of characters which probably indicate shell scripts but native commands won't reject. r=khuey --HG-- extra : rebase_source : 38ffd729c2972e142673fbca50584c241b4eade0 --- build/pymake/pymake/data.py | 2 +- build/pymake/pymake/process.py | 18 ++++++++++++++---- build/pymake/tests/native-simple.mk | 7 ++++--- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/build/pymake/pymake/data.py b/build/pymake/pymake/data.py index c85d6943431e..46caaa22821b 100644 --- a/build/pymake/pymake/data.py +++ b/build/pymake/pymake/data.py @@ -1386,7 +1386,7 @@ class _NativeWrapper(_CommandWrapper): _CommandWrapper.__init__(self, cline, ignoreErrors, loc, context, **kwargs) # get the module and method to call - parts, badchar = process.clinetoargv(cline) + parts, badchar = process.clinetoargv(cline, blacklist_gray=False) if parts is None: raise DataError("native command '%s': shell metacharacter '%s' in command line" % (cline, badchar), self.loc) if len(parts) < 2: diff --git a/build/pymake/pymake/process.py b/build/pymake/pymake/process.py index b4afac1ede38..78362fe00698 100644 --- a/build/pymake/pymake/process.py +++ b/build/pymake/pymake/process.py @@ -15,19 +15,29 @@ if sys.platform=='win32': _log = logging.getLogger('pymake.process') _escapednewlines = re.compile(r'\\\n') -_blacklist = re.compile(r'[$><;[~`|&()]' + +# Characters that most likely indicate a shell script and that native commands +# should reject +_blacklist = re.compile(r'[$><;\[~`|&]' + r'|\${|(?:^|\s){(?:$|\s)') # Blacklist ${foo} and { commands } +# Characters that probably indicate a shell script, but that native commands +# shouldn't just reject +_graylist = re.compile(r'[()]') +# Characters that indicate we need to glob _needsglob = re.compile(r'[\*\?]') -def clinetoargv(cline): + +def clinetoargv(cline, blacklist_gray): """ If this command line can safely skip the shell, return an argv array. @returns argv, badchar """ - str = _escapednewlines.sub('', cline) m = _blacklist.search(str) if m is not None: return None, m.group(0) + if blacklist_gray: + m = _graylist.search(str) + if m is not None: + return None, m.group(0) args = shlex.split(str, comments=True) @@ -65,7 +75,7 @@ def call(cline, env, cwd, loc, cb, context, echo, justprint=False): if msys and cline.startswith('/'): shellreason = "command starts with /" else: - argv, badchar = clinetoargv(cline) + argv, badchar = clinetoargv(cline, blacklist_gray=True) if argv is None: shellreason = "command contains shell-special character '%s'" % (badchar,) elif len(argv) and argv[0] in shellwords: diff --git a/build/pymake/tests/native-simple.mk b/build/pymake/tests/native-simple.mk index c67a89908b63..626a58670536 100644 --- a/build/pymake/tests/native-simple.mk +++ b/build/pymake/tests/native-simple.mk @@ -2,10 +2,11 @@ ifndef TOUCH TOUCH = touch endif -all: testfile {testfile2} +all: testfile {testfile2} (testfile3) test -f testfile test -f {testfile2} + test -f "(testfile3)" @echo TEST-PASS -testfile {testfile2}: - $(TOUCH) $@ +testfile {testfile2} (testfile3): + $(TOUCH) "$@" From 9a29de7e96d07ec048f59520927d4c82de26b333 Mon Sep 17 00:00:00 2001 From: Siddharth Agarwal Date: Wed, 8 Aug 2012 00:49:55 +0530 Subject: [PATCH 050/169] Bug 585011 - Invoke cl.py as a pymake native command. r=ted --HG-- extra : rebase_source : c8e2bfe4e17c39c27e33cfade0e3a6984d104c2f --- config/config.mk | 11 +++++++++++ configure.in | 6 ------ js/src/config/config.mk | 11 +++++++++++ js/src/configure.in | 7 ------- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/config/config.mk b/config/config.mk index be36ec9df03e..410a3c8621dd 100644 --- a/config/config.mk +++ b/config/config.mk @@ -120,6 +120,17 @@ FINAL_LINK_COMP_NAMES = $(DEPTH)/config/final-link-comp-names MOZ_UNICHARUTIL_LIBS = $(LIBXUL_DIST)/lib/$(LIB_PREFIX)unicharutil_s.$(LIB_SUFFIX) MOZ_WIDGET_SUPPORT_LIBS = $(DIST)/lib/$(LIB_PREFIX)widgetsupport_s.$(LIB_SUFFIX) +ifdef _MSC_VER +ifdef .PYMAKE +PYCOMMANDPATH += $(topsrcdir)/build +CC_WRAPPER ?= %cl InvokeClWithDependencyGeneration +CXX_WRAPPER ?= %cl InvokeClWithDependencyGeneration +else +CC_WRAPPER ?= $(PYTHON) -O $(topsrcdir)/build/cl.py +CXX_WRAPPER ?= $(PYTHON) -O $(topsrcdir)/build/cl.py +endif # .PYMAKE +endif # _MSC_VER + CC := $(CC_WRAPPER) $(CC) CXX := $(CXX_WRAPPER) $(CXX) MKDIR ?= mkdir diff --git a/configure.in b/configure.in index fb862d752b8b..aa7cf98947eb 100644 --- a/configure.in +++ b/configure.in @@ -7690,9 +7690,6 @@ else fi AC_SUBST(CL_INCLUDES_PREFIX) rm -f dummy-hello.c - dnl cl.py provides dependency generation for MSVC - CC_WRAPPER='$(PYTHON) -O $(topsrcdir)/build/cl.py' - CXX_WRAPPER='$(PYTHON) -O $(topsrcdir)/build/cl.py' COMPILER_DEPEND=1 fi fi @@ -7701,9 +7698,6 @@ MDDEPDIR='.deps' AC_SUBST(MOZ_AUTO_DEPS) AC_SUBST(COMPILER_DEPEND) AC_SUBST(MDDEPDIR) -AC_SUBST(CC_WRAPPER) -AC_SUBST(CXX_WRAPPER) - dnl ======================================================== dnl = diff --git a/js/src/config/config.mk b/js/src/config/config.mk index be36ec9df03e..410a3c8621dd 100644 --- a/js/src/config/config.mk +++ b/js/src/config/config.mk @@ -120,6 +120,17 @@ FINAL_LINK_COMP_NAMES = $(DEPTH)/config/final-link-comp-names MOZ_UNICHARUTIL_LIBS = $(LIBXUL_DIST)/lib/$(LIB_PREFIX)unicharutil_s.$(LIB_SUFFIX) MOZ_WIDGET_SUPPORT_LIBS = $(DIST)/lib/$(LIB_PREFIX)widgetsupport_s.$(LIB_SUFFIX) +ifdef _MSC_VER +ifdef .PYMAKE +PYCOMMANDPATH += $(topsrcdir)/build +CC_WRAPPER ?= %cl InvokeClWithDependencyGeneration +CXX_WRAPPER ?= %cl InvokeClWithDependencyGeneration +else +CC_WRAPPER ?= $(PYTHON) -O $(topsrcdir)/build/cl.py +CXX_WRAPPER ?= $(PYTHON) -O $(topsrcdir)/build/cl.py +endif # .PYMAKE +endif # _MSC_VER + CC := $(CC_WRAPPER) $(CC) CXX := $(CXX_WRAPPER) $(CXX) MKDIR ?= mkdir diff --git a/js/src/configure.in b/js/src/configure.in index c4bc28550292..9328848daab1 100644 --- a/js/src/configure.in +++ b/js/src/configure.in @@ -4119,10 +4119,6 @@ else fi AC_SUBST(CL_INCLUDES_PREFIX) rm -f dummy-hello.c - _topsrcdirwin=`cd \`dirname $0\`; pwd -W` - dnl cl.py provides dependency generation for MSVC - CC_WRAPPER="$PYTHON -O $_topsrcdirwin/build/cl.py" - CXX_WRAPPER="$PYTHON -O $_topsrcdirwin/build/cl.py" COMPILER_DEPEND=1 fi fi @@ -4131,9 +4127,6 @@ MDDEPDIR='.deps' AC_SUBST(MOZ_AUTO_DEPS) AC_SUBST(COMPILER_DEPEND) AC_SUBST(MDDEPDIR) -AC_SUBST(CC_WRAPPER) -AC_SUBST(CXX_WRAPPER) - dnl ======================================================== dnl = Link js shell to system readline From 25ef1560974faaf877d6c9c1d8783fbd0d39f8a2 Mon Sep 17 00:00:00 2001 From: Josh Aas Date: Tue, 7 Aug 2012 15:28:16 -0400 Subject: [PATCH 051/169] Bug 574229: Open new window in the current OS X space when opening from the dock menu. r=gavin --- browser/base/content/macBrowserOverlay.xul | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/browser/base/content/macBrowserOverlay.xul b/browser/base/content/macBrowserOverlay.xul index 1746c61242df..94214126da2d 100644 --- a/browser/base/content/macBrowserOverlay.xul +++ b/browser/base/content/macBrowserOverlay.xul @@ -27,11 +27,15 @@ + + + + + +Mozilla Bug 666041 +

    +
    +
    +
    +
    +
    + + From c7927560df05dc62efbcecd7a9f256bafb8998b2 Mon Sep 17 00:00:00 2001 From: Kyle Huey Date: Tue, 7 Aug 2012 14:38:46 -0700 Subject: [PATCH 065/169] Bug 774732: Always modify the busy count in NotifyRunnable to avoid busy count mismatches. r=bent --- dom/workers/WorkerPrivate.cpp | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index 3cdfe1226693..99027bbdddb3 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -832,14 +832,12 @@ public: class NotifyRunnable : public WorkerControlRunnable { - bool mFromJSObjectFinalizer; Status mStatus; public: - NotifyRunnable(WorkerPrivate* aWorkerPrivate, bool aFromJSObjectFinalizer, - Status aStatus) + NotifyRunnable(WorkerPrivate* aWorkerPrivate, Status aStatus) : WorkerControlRunnable(aWorkerPrivate, WorkerThread, UnchangedBusyCount), - mFromJSObjectFinalizer(aFromJSObjectFinalizer), mStatus(aStatus) + mStatus(aStatus) { NS_ASSERTION(aStatus == Terminating || aStatus == Canceling || aStatus == Killing, "Bad status!"); @@ -849,12 +847,8 @@ public: PreDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate) { // Modify here, but not in PostRun! This busy count addition will be matched - // by the CloseEventRunnable. If we're running from a finalizer there is no - // need to modify the count because future changes to the busy count will - // have no effect. - return mFromJSObjectFinalizer ? - true : - aWorkerPrivate->ModifyBusyCount(aCx, true); + // by the CloseEventRunnable. + return aWorkerPrivate->ModifyBusyCount(aCx, true); } bool @@ -2019,7 +2013,7 @@ WorkerPrivateParent::NotifyPrivate(JSContext* aCx, Status aStatus) mQueuedRunnables.Clear(); nsRefPtr runnable = - new NotifyRunnable(ParentAsWorkerPrivate(), !aCx, aStatus); + new NotifyRunnable(ParentAsWorkerPrivate(), aStatus); return runnable->Dispatch(aCx); } @@ -2163,7 +2157,7 @@ WorkerPrivateParent::ModifyBusyCount(JSContext* aCx, bool aIncrease) NS_ASSERTION(aIncrease || mBusyCount, "Mismatched busy count mods!"); if (aIncrease) { - if (mBusyCount++ == 0) { + if (mBusyCount++ == 0 && mJSObject) { if (!RootJSObject(aCx, true)) { return false; } @@ -2171,7 +2165,7 @@ WorkerPrivateParent::ModifyBusyCount(JSContext* aCx, bool aIncrease) return true; } - if (--mBusyCount == 0) { + if (--mBusyCount == 0 && mJSObject) { if (!RootJSObject(aCx, false)) { return false; } @@ -2198,6 +2192,7 @@ WorkerPrivateParent::RootJSObject(JSContext* aCx, bool aRoot) if (aRoot != mJSObjectRooted) { if (aRoot) { + NS_ASSERTION(mJSObject, "Nothing to root?"); if (!JS_AddNamedObjectRoot(aCx, &mJSObject, "Worker root")) { NS_WARNING("JS_AddNamedObjectRoot failed!"); return false; From 22b5f769a01b9e9b0dcd04f80997b07fcc4f7837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Tue, 7 Aug 2012 17:49:30 -0400 Subject: [PATCH 066/169] Bug 777122 - Add telemetry reporting of late writes. r=jlebar. patch2: Enable on release builds and record the last write to disk. --- xpcom/build/mozPoisonWriteMac.cpp | 254 +++++++++++++++++++++++++++--- 1 file changed, 233 insertions(+), 21 deletions(-) diff --git a/xpcom/build/mozPoisonWriteMac.cpp b/xpcom/build/mozPoisonWriteMac.cpp index 71a2726a7831..3d3822e92261 100644 --- a/xpcom/build/mozPoisonWriteMac.cpp +++ b/xpcom/build/mozPoisonWriteMac.cpp @@ -10,8 +10,15 @@ #include "mozilla/Assertions.h" #include "mozilla/Scoped.h" #include "mozilla/Mutex.h" +#include "mozilla/Telemetry.h" #include "nsStackWalk.h" +#include "nsPrintfCString.h" #include "mach_override.h" +#include "prio.h" +#include "plstr.h" +#include "nsCOMPtr.h" +#include "nsAppDirectoryServiceDefs.h" +#include "nsDirectoryServiceUtils.h" #include #include #include @@ -31,12 +38,200 @@ struct FuncData { // 'Function' after it has been replaced. }; + +// FIXME: duplicated code. The HangMonitor could also report processed addresses, +// this class should be moved somewhere it can be shared. +class ProcessedStack +{ +public: + ProcessedStack() : mProcessed(false) + { + } + void Reserve(unsigned int n) + { + mStack.reserve(n); + } + size_t GetStackSize() + { + return mStack.size(); + } + struct ProcessedStackFrame + { + uintptr_t mOffset; + uint16_t mModIndex; + }; + ProcessedStackFrame GetFrame(unsigned aIndex) + { + const StackFrame &Frame = mStack[aIndex]; + ProcessedStackFrame Ret = { Frame.mPC, Frame.mModIndex }; + return Ret; + } + size_t GetNumModules() + { + MOZ_ASSERT(mProcessed); + return mModules.GetSize(); + } + const char *GetModuleName(unsigned aIndex) + { + MOZ_ASSERT(mProcessed); + return mModules.GetEntry(aIndex).GetName(); + } + void AddStackFrame(uintptr_t aPC) + { + MOZ_ASSERT(!mProcessed); + StackFrame Frame = {aPC, static_cast(mStack.size()), + std::numeric_limits::max()}; + mStack.push_back(Frame); + } + void Process() + { + mProcessed = true; + mModules = SharedLibraryInfo::GetInfoForSelf(); + mModules.SortByAddress(); + + // Remove all modules not referenced by a PC on the stack + std::sort(mStack.begin(), mStack.end(), CompareByPC); + + size_t moduleIndex = 0; + size_t stackIndex = 0; + size_t stackSize = mStack.size(); + + while (moduleIndex < mModules.GetSize()) { + SharedLibrary& module = mModules.GetEntry(moduleIndex); + uintptr_t moduleStart = module.GetStart(); + uintptr_t moduleEnd = module.GetEnd() - 1; + // the interval is [moduleStart, moduleEnd) + + bool moduleReferenced = false; + for (;stackIndex < stackSize; ++stackIndex) { + uintptr_t pc = mStack[stackIndex].mPC; + if (pc >= moduleEnd) + break; + + if (pc >= moduleStart) { + // If the current PC is within the current module, mark + // module as used + moduleReferenced = true; + mStack[stackIndex].mPC -= moduleStart; + mStack[stackIndex].mModIndex = moduleIndex; + } else { + // PC does not belong to any module. It is probably from + // the JIT. Use a fixed mPC so that we don't get different + // stacks on different runs. + mStack[stackIndex].mPC = + std::numeric_limits::max(); + } + } + + if (moduleReferenced) { + ++moduleIndex; + } else { + // Remove module if no PCs within its address range + mModules.RemoveEntries(moduleIndex, moduleIndex + 1); + } + } + + for (;stackIndex < stackSize; ++stackIndex) { + // These PCs are past the last module. + mStack[stackIndex].mPC = std::numeric_limits::max(); + } + + std::sort(mStack.begin(), mStack.end(), CompareByIndex); + } + +private: + struct StackFrame + { + uintptr_t mPC; // The program counter at this position in the call stack. + uint16_t mIndex; // The number of this frame in the call stack. + uint16_t mModIndex; // The index of module that has this program counter. + }; + static bool CompareByPC(const StackFrame &a, const StackFrame &b) + { + return a.mPC < b.mPC; + } + static bool CompareByIndex(const StackFrame &a, const StackFrame &b) + { + return a.mIndex < b.mIndex; + } + SharedLibraryInfo mModules; + std::vector mStack; + bool mProcessed; +}; + +void RecordStackWalker(void *aPC, void *aSP, void *aClosure) +{ + ProcessedStack *stack = static_cast(aClosure); + stack->AddStackFrame(reinterpret_cast(aPC)); +} + +char *sProfileDirectory = NULL; + +bool ValidWriteAssert(bool ok) +{ + // On a debug build, just crash. + MOZ_ASSERT(ok); + + if (ok || !sProfileDirectory || !Telemetry::CanRecord()) + return ok; + + // Write the stack and loaded libraries to a file. We can get here + // concurrently from many writes, so we use multiple temporary files. + ProcessedStack stack; + NS_StackWalk(RecordStackWalker, 0, reinterpret_cast(&stack), 0); + stack.Process(); + + nsPrintfCString nameAux("%s%s", sProfileDirectory, + "/Telemetry.LateWriteTmpXXXXXX"); + char *name; + nameAux.GetMutableData(&name); + int fd = mkstemp(name); + MozillaRegisterDebugFD(fd); + FILE *f = fdopen(fd, "w"); + + size_t numModules = stack.GetNumModules(); + fprintf(f, "%zu\n", numModules); + for (int i = 0; i < numModules; ++i) { + const char *name = stack.GetModuleName(i); + fprintf(f, "%s\n", name ? name : ""); + } + + size_t numFrames = stack.GetStackSize(); + fprintf(f, "%zu\n", numFrames); + for (size_t i = 0; i < numFrames; ++i) { + const ProcessedStack::ProcessedStackFrame &frame = stack.GetFrame(i); + // NOTE: We write the offsets, while the atos tool expects a value with + // the virtual address added. For example, running otool -l on the the firefox + // binary shows + // cmd LC_SEGMENT_64 + // cmdsize 632 + // segname __TEXT + // vmaddr 0x0000000100000000 + // so to print the line matching the offset 123 one has to run + // atos -o firefox 0x100000123. + fprintf(f, "%d %jx\n", frame.mModIndex, frame.mOffset); + } + + fflush(f); + MozillaUnRegisterDebugFD(fd); + fclose(f); + + // FIXME: For now we just record the last write. We should write the files + // to filenames that include the md5. That will provide a simple early + // deduplication if the same bug is found in multiple runs. + nsPrintfCString finalName("%s%s", sProfileDirectory, + "/Telemetry.LateWriteFinal-last"); + PR_Delete(finalName.get()); + PR_Rename(name, finalName.get()); + return false; +} + // Wrap aio_write. We have not seen it before, so just assert/report it. typedef ssize_t (*aio_write_t)(struct aiocb *aiocbp); ssize_t wrap_aio_write(struct aiocb *aiocbp); FuncData aio_write_data = { 0, (void*) wrap_aio_write, (void*) aio_write }; ssize_t wrap_aio_write(struct aiocb *aiocbp) { - MOZ_ASSERT(0); + ValidWriteAssert(0); aio_write_t old_write = (aio_write_t) aio_write_data.Buffer; return old_write(aiocbp); } @@ -46,7 +241,7 @@ ssize_t wrap_aio_write(struct aiocb *aiocbp) { typedef ssize_t (*pwrite_t)(int fd, const void *buf, size_t nbyte, off_t offset); template ssize_t wrap_pwrite_temp(int fd, const void *buf, size_t nbyte, off_t offset) { - MOZ_ASSERT(0); + ValidWriteAssert(0); pwrite_t old_write = (pwrite_t) foo.Buffer; return old_write(fd, buf, nbyte, offset); } @@ -184,38 +379,46 @@ void AbortOnBadWrite(int fd, const void *wbuf, size_t count) { struct stat buf; int rv = fstat(fd, &buf); - MOZ_ASSERT(rv == 0); + if (!ValidWriteAssert(rv == 0)) + return; // FIFOs are used for thread communication during shutdown. if ((buf.st_mode & S_IFMT) == S_IFIFO) return; - MyAutoLock lockedScope; + { + MyAutoLock lockedScope; - // Debugging FDs are OK - std::vector &Vec = getDebugFDs(); - if (std::find(Vec.begin(), Vec.end(), fd) != Vec.end()) - return; + // Debugging FDs are OK + std::vector &Vec = getDebugFDs(); + if (std::find(Vec.begin(), Vec.end(), fd) != Vec.end()) + return; + } // For writev we pass NULL in wbuf. We should only get here from // dbm, and it uses write, so assert that we have wbuf. - MOZ_ASSERT(wbuf); + if (!ValidWriteAssert(wbuf)) + return; // As a really bad hack, accept writes that don't change the on disk // content. This is needed because dbm doesn't keep track of dirty bits // and can end up writing the same data to disk twice. Once when the // user (nss) asks it to sync and once when closing the database. - void *wbuf2 = malloc(count); - MOZ_ASSERT(wbuf2); + ScopedFreePtr wbuf2(malloc(count)); + if (!ValidWriteAssert(wbuf2)) + return; off_t pos = lseek(fd, 0, SEEK_CUR); - MOZ_ASSERT(pos != -1); + if (!ValidWriteAssert(pos != -1)) + return; ssize_t r = read(fd, wbuf2, count); - MOZ_ASSERT(r == count); + if (!ValidWriteAssert(r == count)) + return; int cmp = memcmp(wbuf, wbuf2, count); - MOZ_ASSERT(cmp == 0); - free(wbuf2); + if (!ValidWriteAssert(cmp == 0)) + return; off_t pos2 = lseek(fd, pos, SEEK_SET); - MOZ_ASSERT(pos2 == pos); + if (!ValidWriteAssert(pos2 == pos)) + return; } // We cannot use destructors to free the lock and the list of debug fds since @@ -226,6 +429,9 @@ extern "C" void (*__cleanup)(); void FinalCleanup() { if (OldCleanup) OldCleanup(); + if (sProfileDirectory) + PL_strfree(sProfileDirectory); + sProfileDirectory = nullptr; delete &getDebugFDs(); PR_DestroyLock(MyAutoLock::getDebugFDsLock()); } @@ -250,12 +456,18 @@ extern "C" { namespace mozilla { void PoisonWrite() { - // For now only poison writes in debug builds. -#ifndef DEBUG - return; -#endif - PoisoningDisabled = false; + + nsCOMPtr mozFile; + NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(mozFile)); + if (mozFile) { + nsCAutoString nativePath; + nsresult rv = mozFile->GetNativePath(nativePath); + if (NS_SUCCEEDED(rv)) { + sProfileDirectory = PL_strdup(nativePath.get()); + } + } + OldCleanup = __cleanup; __cleanup = FinalCleanup; From ed4dd5cc8f8dbccc1d53cacc08e5c4d57565d44e Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Tue, 7 Aug 2012 14:48:13 -0700 Subject: [PATCH 067/169] Bug 778468 (followup) - Add missing import to GeckoApp.java --HG-- extra : rebase_source : eb1fec6f975604c4bce94e68f52b965ecd410cca --- mobile/android/base/GeckoApp.java | 1 + 1 file changed, 1 insertion(+) diff --git a/mobile/android/base/GeckoApp.java b/mobile/android/base/GeckoApp.java index 28a43f1b3b6a..548c9639d221 100644 --- a/mobile/android/base/GeckoApp.java +++ b/mobile/android/base/GeckoApp.java @@ -14,6 +14,7 @@ import org.mozilla.gecko.gfx.PointUtils; import org.mozilla.gecko.ui.PanZoomController; import org.mozilla.gecko.util.GeckoAsyncTask; import org.mozilla.gecko.util.GeckoEventListener; +import org.mozilla.gecko.util.GeckoEventResponder; import org.json.JSONArray; import org.json.JSONException; From c7adbabdd50d9f2a5218d8fa9f7120203e04f0b5 Mon Sep 17 00:00:00 2001 From: Gregor Wagner Date: Tue, 7 Aug 2012 15:02:37 -0700 Subject: [PATCH 068/169] Bug 736883 - Contacts API: Add pictures. r=bent --- dom/contacts/ContactManager.js | 17 +- dom/contacts/tests/Makefile.in | 1 + dom/contacts/tests/test_contacts_basics.html | 2 - dom/contacts/tests/test_contacts_blobs.html | 324 ++++++++++++++++++ .../contacts/nsIDOMContactProperties.idl | 2 +- testing/mochitest/android.json | 1 + 6 files changed, 343 insertions(+), 4 deletions(-) create mode 100644 dom/contacts/tests/test_contacts_blobs.html diff --git a/dom/contacts/ContactManager.js b/dom/contacts/ContactManager.js index c9f9cb4ad648..04407ba06672 100644 --- a/dom/contacts/ContactManager.js +++ b/dom/contacts/ContactManager.js @@ -168,6 +168,21 @@ Contact.prototype = { } }; + function _checkBlobArray(aBlob) { + if (Array.isArray(aBlob)) { + for (let i = 0; i < aBlob.length; i++) { + if (typeof aBlob != 'object') { + return null; + } + if (!(aBlob[i] instanceof Components.interfaces.nsIDOMBlob)) { + return null; + } + } + return aBlob; + } + return null; + }; + this.name = _create(aProp.name) || null; this.honorificPrefix = _create(aProp.honorificPrefix) || null; this.givenName = _create(aProp.givenName) || null; @@ -185,7 +200,7 @@ Contact.prototype = { this.email = null; } - this.photo = _create(aProp.photo) || null; + this.photo = _checkBlobArray(aProp.photo) || null; this.url = _create(aProp.url) || null; this.category = _create(aProp.category) || null; diff --git a/dom/contacts/tests/Makefile.in b/dom/contacts/tests/Makefile.in index 9f53a7ccb2b8..3da19e6dfd90 100644 --- a/dom/contacts/tests/Makefile.in +++ b/dom/contacts/tests/Makefile.in @@ -17,6 +17,7 @@ DIRS = \ MOCHITEST_FILES = \ test_contacts_basics.html \ test_contacts_events.html \ + test_contacts_blobs.html \ $(NULL) include $(topsrcdir)/config/rules.mk diff --git a/dom/contacts/tests/test_contacts_basics.html b/dom/contacts/tests/test_contacts_basics.html index 52f5d1f6584d..3d76dfcc9144 100644 --- a/dom/contacts/tests/test_contacts_basics.html +++ b/dom/contacts/tests/test_contacts_basics.html @@ -99,7 +99,6 @@ var properties2 = { jobTitle: ["boss", "superboss"], bday: new Date("1980, 12, 01"), note: "test note", - photo: ["pic1", "pic2"], category: ["cat1", "cat2"], url: ["www.1.com", "www.2.com"], anniversary: new Date("2000, 12, 01"), @@ -165,7 +164,6 @@ function checkContacts(contact1, contact2) { checkStr(contact1.familyName, contact2.familyName, "Same familyName"); checkStr(contact1.honorificSuffix, contact2.honorificSuffix, "Same honorificSuffix"); checkStr(contact1.nickname, contact2.nickname, "Same nickname"); - checkStr(contact1.photo, contact2.photo, "Same photo"); checkStr(contact1.url, contact2.url, "Same url"); checkStr(contact1.category, contact2.category, "Same category"); checkStr(contact1.org, contact2.org, "Same org"); diff --git a/dom/contacts/tests/test_contacts_blobs.html b/dom/contacts/tests/test_contacts_blobs.html new file mode 100644 index 000000000000..0c0d7b3a0121 --- /dev/null +++ b/dom/contacts/tests/test_contacts_blobs.html @@ -0,0 +1,324 @@ + + + + + Test for Bug {674720} WebContacts + + + + + + +Mozilla Bug {674720} +

    + +
    +
    +
    + + \ No newline at end of file diff --git a/dom/interfaces/contacts/nsIDOMContactProperties.idl b/dom/interfaces/contacts/nsIDOMContactProperties.idl index 082bad9575f1..c647b14dad85 100644 --- a/dom/interfaces/contacts/nsIDOMContactProperties.idl +++ b/dom/interfaces/contacts/nsIDOMContactProperties.idl @@ -54,7 +54,7 @@ interface nsIDOMContactProperties : nsISupports attribute jsval honorificSuffix; // DOMString[] attribute jsval nickname; // DOMString[] attribute jsval email; // ContactEmail[] - attribute jsval photo; // DOMString[] + attribute jsval photo; // nsIDOMBlob[] attribute jsval url; // DOMString[] attribute jsval category; // DOMString[] attribute jsval adr; // ContactAddress[] diff --git a/testing/mochitest/android.json b/testing/mochitest/android.json index e05cf49ce5fe..78dfa7924706 100644 --- a/testing/mochitest/android.json +++ b/testing/mochitest/android.json @@ -146,6 +146,7 @@ "dom/network/tests/test_network_basics.html": "", "dom/settings/tests/test_settings_events.html": "", "dom/settings/tests/test_settings_basics.html": "", + "dom/contacts/tests/test_contacts_blobs.html": "", "dom/contacts/tests/test_contacts_basics.html": "", "dom/contacts/tests/test_contacts_events.html": "", "dom/sms/tests/test_sms_basics.html": "", From 71cc2053eef4607215da224022672706328c58e3 Mon Sep 17 00:00:00 2001 From: John Schoenick Date: Tue, 7 Aug 2012 15:13:32 -0700 Subject: [PATCH 069/169] Bug 778858 - Enable OOP plugins in webapprt by default. r=myk --- webapprt/prefs.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/webapprt/prefs.js b/webapprt/prefs.js index d8355a41b9ba..4e2243b8d77a 100644 --- a/webapprt/prefs.js +++ b/webapprt/prefs.js @@ -36,3 +36,16 @@ pref("full-screen-api.enabled", true); pref("general.smoothScroll", true); pref("plugin.allowed_types", "application/x-shockwave-flash,application/futuresplash"); + +// The default for this pref reflects whether the build is capable of IPC. +// (Turning it on in a no-IPC build will have no effect.) +#ifdef XP_MACOSX +// i386 ipc preferences +pref("dom.ipc.plugins.enabled.i386", false); +pref("dom.ipc.plugins.enabled.i386.flash player.plugin", true); +// x86_64 ipc preferences +pref("dom.ipc.plugins.enabled.x86_64", true); +#else +pref("dom.ipc.plugins.enabled", true); +#endif + From 056b8973b8421320ef7b6419ae9998c24a82746f Mon Sep 17 00:00:00 2001 From: Jason Duell Date: Tue, 7 Aug 2012 15:46:33 -0700 Subject: [PATCH 070/169] bug 780750 - HTTP cache never gets used/fixed if wrong permissions on CACHE_MAP file. r=hurley --- netwerk/cache/nsDiskCacheDevice.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/netwerk/cache/nsDiskCacheDevice.cpp b/netwerk/cache/nsDiskCacheDevice.cpp index b647e9170155..4fb009e4f579 100644 --- a/netwerk/cache/nsDiskCacheDevice.cpp +++ b/netwerk/cache/nsDiskCacheDevice.cpp @@ -989,11 +989,13 @@ nsDiskCacheDevice::OpenDiskCache() nsDiskCache::CorruptCacheInfo corruptInfo; rv = mCacheMap.Open(mCacheDirectory, &corruptInfo); - // move "corrupt" caches to trash if (NS_SUCCEEDED(rv)) { Telemetry::Accumulate(Telemetry::DISK_CACHE_CORRUPT_DETAILS, corruptInfo); - } else if (rv == NS_ERROR_FILE_CORRUPTED) { + } else if (rv == NS_ERROR_ALREADY_INITIALIZED) { + NS_WARNING("nsDiskCacheDevice::OpenDiskCache: already open!"); + } else { + // Consider cache corrupt: delete it Telemetry::Accumulate(Telemetry::DISK_CACHE_CORRUPT_DETAILS, corruptInfo); // delay delete by 1 minute to avoid IO thrash at startup @@ -1001,10 +1003,6 @@ nsDiskCacheDevice::OpenDiskCache() if (NS_FAILED(rv)) return rv; exists = false; - } else { - // don't gather telemetry for "corrupt cache" for new profile - // where cache doesn't exist (most likely case if we're here). - return rv; } } From 8ba592bd41c5b7538b8b2334e856a6163e16f2dc Mon Sep 17 00:00:00 2001 From: Nick Hurley Date: Tue, 7 Aug 2012 15:46:33 -0700 Subject: [PATCH 071/169] bug 709297 - reduce max cache size to 350MiB the next time we have to trash the cache. r=jduell --- modules/libpref/src/init/all.js | 2 + netwerk/cache/nsCacheService.cpp | 115 ++++++++++++++++-- netwerk/cache/nsCacheService.h | 6 + netwerk/cache/nsDiskCacheDevice.cpp | 1 + .../telemetry/TelemetryHistograms.h | 1 + 5 files changed, 114 insertions(+), 11 deletions(-) diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index eca51544bba3..98121d42b62f 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -36,6 +36,8 @@ pref("browser.cache.disk.enable", true); pref("browser.cache.disk.smart_size.first_run", true); // Does the user want smart-sizing? pref("browser.cache.disk.smart_size.enabled", true); +// Which max value should we use for smart-sizing? +pref("browser.cache.disk.smart_size.use_old_max", true); // Size (in KB) explicitly set by the user. Used when smart_size.enabled == false pref("browser.cache.disk.capacity", 256000); // Max-size (in KB) for entries in disk cache. Set to -1 for no limit. diff --git a/netwerk/cache/nsCacheService.cpp b/netwerk/cache/nsCacheService.cpp index a904acf9b8c5..9a523629f298 100644 --- a/netwerk/cache/nsCacheService.cpp +++ b/netwerk/cache/nsCacheService.cpp @@ -57,6 +57,9 @@ using namespace mozilla; #define DISK_CACHE_MAX_ENTRY_SIZE_PREF "browser.cache.disk.max_entry_size" #define DISK_CACHE_CAPACITY 256000 +#define DISK_CACHE_USE_OLD_MAX_SMART_SIZE_PREF \ + "browser.cache.disk.smart_size.use_old_max" + #define OFFLINE_CACHE_ENABLE_PREF "browser.cache.offline.enable" #define OFFLINE_CACHE_DIR_PREF "browser.cache.offline.parent_directory" #define OFFLINE_CACHE_CAPACITY_PREF "browser.cache.offline.capacity" @@ -84,6 +87,7 @@ static const char * prefList[] = { DISK_CACHE_CAPACITY_PREF, DISK_CACHE_DIR_PREF, DISK_CACHE_MAX_ENTRY_SIZE_PREF, + DISK_CACHE_USE_OLD_MAX_SMART_SIZE_PREF, OFFLINE_CACHE_ENABLE_PREF, OFFLINE_CACHE_CAPACITY_PREF, OFFLINE_CACHE_DIR_PREF, @@ -100,8 +104,10 @@ const PRInt32 DEFAULT_CACHE_SIZE = 250 * 1024; // 250 MB const PRInt32 MIN_CACHE_SIZE = 50 * 1024; // 50 MB #ifdef ANDROID const PRInt32 MAX_CACHE_SIZE = 200 * 1024; // 200 MB +const PRInt32 OLD_MAX_CACHE_SIZE = 200 * 1024; // 200 MB #else -const PRInt32 MAX_CACHE_SIZE = 1024 * 1024; // 1 GB +const PRInt32 MAX_CACHE_SIZE = 350 * 1024; // 350 MB +const PRInt32 OLD_MAX_CACHE_SIZE = 1024 * 1024; // 1 GB #endif // Default cache size was 50 MB for many years until FF 4: const PRInt32 PRE_GECKO_2_0_DEFAULT_CACHE_SIZE = 50 * 1024; @@ -118,6 +124,7 @@ public: , mDiskCacheCapacity(0) , mDiskCacheMaxEntrySize(-1) // -1 means "no limit" , mSmartSizeEnabled(false) + , mUseOldMaxSmartSize(false) , mOfflineCacheEnabled(false) , mOfflineCacheCapacity(0) , mMemoryCacheEnabled(true) @@ -142,6 +149,9 @@ public: nsIFile * DiskCacheParentDirectory() { return mDiskCacheParentDirectory; } bool SmartSizeEnabled() { return mSmartSizeEnabled; } + bool UseOldMaxSmartSize() { return mUseOldMaxSmartSize; } + void SetUseNewMaxSmartSize() { mUseOldMaxSmartSize = false; } + bool OfflineCacheEnabled(); PRInt32 OfflineCacheCapacity() { return mOfflineCacheCapacity; } nsIFile * OfflineCacheParentDirectory() { return mOfflineCacheParentDirectory; } @@ -155,7 +165,8 @@ public: bool SanitizeAtShutdown() { return mSanitizeOnShutdown && mClearCacheOnShutdown; } static PRUint32 GetSmartCacheSize(const nsAString& cachePath, - PRUint32 currentSize); + PRUint32 currentSize, + bool useOldMaxSmartSize); private: bool PermittedToSmartSize(nsIPrefBranch*, bool firstRun); @@ -167,6 +178,8 @@ private: nsCOMPtr mDiskCacheParentDirectory; bool mSmartSizeEnabled; + bool mUseOldMaxSmartSize; + bool mOfflineCacheEnabled; PRInt32 mOfflineCacheCapacity; // in kilobytes nsCOMPtr mOfflineCacheParentDirectory; @@ -242,9 +255,11 @@ private: class nsGetSmartSizeEvent: public nsRunnable { public: - nsGetSmartSizeEvent(const nsAString& cachePath, PRUint32 currentSize) + nsGetSmartSizeEvent(const nsAString& cachePath, PRUint32 currentSize, + bool useOldMaxSmartSize) : mCachePath(cachePath) , mCurrentSize(currentSize) + , mUseOldMaxSmartSize(useOldMaxSmartSize) {} // Calculates user's disk space available on a background thread and @@ -253,7 +268,8 @@ public: { PRUint32 size; size = nsCacheProfilePrefObserver::GetSmartCacheSize(mCachePath, - mCurrentSize); + mCurrentSize, + mUseOldMaxSmartSize); NS_DispatchToMainThread(new nsSetSmartSizeEvent(size)); return NS_OK; } @@ -261,6 +277,7 @@ public: private: nsString mCachePath; PRUint32 mCurrentSize; + bool mUseOldMaxSmartSize; }; class nsBlockOnCacheThreadEvent : public nsRunnable { @@ -429,6 +446,11 @@ nsCacheProfilePrefObserver::Observe(nsISupports * subject, mDiskCacheCapacity = NS_MAX(0, newCapacity); nsCacheService::SetDiskCacheCapacity(mDiskCacheCapacity); } + } else if (!strcmp(DISK_CACHE_USE_OLD_MAX_SMART_SIZE_PREF, data.get())) { + rv = branch->GetBoolPref(DISK_CACHE_USE_OLD_MAX_SMART_SIZE_PREF, + &mUseOldMaxSmartSize); + if (NS_FAILED(rv)) + return rv; } else if (!strcmp(DISK_CACHE_MAX_ENTRY_SIZE_PREF, data.get())) { PRInt32 newMaxSize; rv = branch->GetIntPref(DISK_CACHE_MAX_ENTRY_SIZE_PREF, @@ -524,10 +546,12 @@ nsCacheProfilePrefObserver::Observe(nsISupports * subject, // Returns default ("smart") size (in KB) of cache, given available disk space // (also in KB) static PRUint32 -SmartCacheSize(const PRUint32 availKB) +SmartCacheSize(const PRUint32 availKB, bool useOldMaxSmartSize) { + PRUint32 maxSize = useOldMaxSmartSize ? OLD_MAX_CACHE_SIZE : MAX_CACHE_SIZE; + if (availKB > 100 * 1024 * 1024) - return MAX_CACHE_SIZE; // skip computing if we're over 100 GB + return maxSize; // skip computing if we're over 100 GB // Grow/shrink in 10 MB units, deliberately, so that in the common case we // don't shrink cache and evict items every time we startup (it's important @@ -563,7 +587,7 @@ SmartCacheSize(const PRUint32 availKB) sz10MBs += NS_MAX(5, avail10MBs * .4); #endif - return NS_MIN(MAX_CACHE_SIZE, sz10MBs * 10 * 1024); + return NS_MIN(maxSize, sz10MBs * 10 * 1024); } /* Computes our best guess for the default size of the user's disk cache, @@ -579,7 +603,8 @@ SmartCacheSize(const PRUint32 availKB) */ PRUint32 nsCacheProfilePrefObserver::GetSmartCacheSize(const nsAString& cachePath, - PRUint32 currentSize) + PRUint32 currentSize, + bool useOldMaxSmartSize) { // Check for free space on device where cache directory lives nsresult rv; @@ -595,7 +620,8 @@ nsCacheProfilePrefObserver::GetSmartCacheSize(const nsAString& cachePath, if (NS_FAILED(rv)) return DEFAULT_CACHE_SIZE; - return SmartCacheSize((bytesAvailable / 1024) + currentSize); + return SmartCacheSize((bytesAvailable / 1024) + currentSize, + useOldMaxSmartSize); } /* Determine if we are permitted to dynamically size the user's disk cache based @@ -626,7 +652,8 @@ nsCacheProfilePrefObserver::PermittedToSmartSize(nsIPrefBranch* branch, bool } // Set manual setting to MAX cache size as starting val for any // adjustment by user: (bug 559942 comment 65) - branch->SetIntPref(DISK_CACHE_CAPACITY_PREF, MAX_CACHE_SIZE); + PRInt32 maxSize = mUseOldMaxSmartSize ? OLD_MAX_CACHE_SIZE : MAX_CACHE_SIZE; + branch->SetIntPref(DISK_CACHE_CAPACITY_PREF, maxSize); } rv = branch->GetBoolPref(DISK_CACHE_SMART_SIZE_ENABLED_PREF, @@ -657,6 +684,9 @@ nsCacheProfilePrefObserver::ReadPrefs(nsIPrefBranch* branch) (void) branch->GetComplexValue(DISK_CACHE_DIR_PREF, // ignore error NS_GET_IID(nsIFile), getter_AddRefs(mDiskCacheParentDirectory)); + + (void) branch->GetBoolPref(DISK_CACHE_USE_OLD_MAX_SMART_SIZE_PREF, + &mUseOldMaxSmartSize); if (!mDiskCacheParentDirectory) { nsCOMPtr directory; @@ -1538,6 +1568,9 @@ nsCacheService::CreateDiskDevice() return rv; } + Telemetry::Accumulate(Telemetry::DISK_CACHE_SMART_SIZE_USING_OLD_MAX, + mObserver->UseOldMaxSmartSize()); + NS_ASSERTION(!mSmartSizeTimer, "Smartsize timer was already fired!"); // Disk device is usually created during the startup. Delay smart size @@ -1561,6 +1594,65 @@ nsCacheService::CreateDiskDevice() return NS_OK; } +// Runnable sent from cache thread to main thread +class nsDisableOldMaxSmartSizePrefEvent: public nsRunnable +{ +public: + nsDisableOldMaxSmartSizePrefEvent() {} + + NS_IMETHOD Run() + { + // Main thread may have already called nsCacheService::Shutdown + if (!nsCacheService::gService || !nsCacheService::gService->mObserver) + return NS_ERROR_NOT_AVAILABLE; + + nsDisableOldMaxSmartSizePrefEvent::DisableOldMaxSmartSizePref(true); + return NS_OK; + } + + static void DisableOldMaxSmartSizePref(bool async) + { + nsCOMPtr prefService = do_GetService(NS_PREFSERVICE_CONTRACTID); + if (!prefService) { + return; + } + + nsCOMPtr branch; + nsresult rv = prefService->GetDefaultBranch(nullptr, getter_AddRefs(branch)); + if (NS_FAILED(rv)) { + return; + } + + rv = branch->SetBoolPref(DISK_CACHE_USE_OLD_MAX_SMART_SIZE_PREF, false); + if (NS_FAILED(rv)) { + return; + } + + if (async) { + nsCacheService::SetDiskSmartSize(); + } else { + nsCacheService::gService->SetDiskSmartSize_Locked(); + } + } +}; + +void +nsCacheService::MarkStartingFresh() +{ + if (!gService->mObserver->UseOldMaxSmartSize()) { + // Already using new max, nothing to do here + return; + } + + gService->mObserver->SetUseNewMaxSmartSize(); + + if (NS_IsMainThread()) { + nsDisableOldMaxSmartSizePrefEvent::DisableOldMaxSmartSizePref(false); + } else { + NS_DispatchToMainThread(new nsDisableOldMaxSmartSizePrefEvent()); + } +} + nsresult nsCacheService::GetOfflineDevice(nsOfflineCacheDevice **aDevice) { @@ -2898,7 +2990,8 @@ nsCacheService::SetDiskSmartSize_Locked() rv = mObserver->DiskCacheParentDirectory()->GetPath(cachePath); if (NS_SUCCEEDED(rv)) { nsCOMPtr event = - new nsGetSmartSizeEvent(cachePath, mDiskDevice->getCacheSize()); + new nsGetSmartSizeEvent(cachePath, mDiskDevice->getCacheSize(), + mObserver->UseOldMaxSmartSize()); DispatchToCacheIOThread(event); } else { return NS_ERROR_FAILURE; diff --git a/netwerk/cache/nsCacheService.h b/netwerk/cache/nsCacheService.h index 424cf4e81701..b73b6e8a3468 100644 --- a/netwerk/cache/nsCacheService.h +++ b/netwerk/cache/nsCacheService.h @@ -108,6 +108,11 @@ public: static bool IsStorageEnabledForPolicy_Locked(nsCacheStoragePolicy policy); + /** + * Called by disk cache to notify us to use the new max smart size + */ + static void MarkStartingFresh(); + /** * Methods called by nsApplicationCacheService */ @@ -184,6 +189,7 @@ private: friend class nsBlockOnCacheThreadEvent; friend class nsSetDiskSmartSizeCallback; friend class nsDoomEvent; + friend class nsDisableOldMaxSmartSizePrefEvent; /** * Internal Methods diff --git a/netwerk/cache/nsDiskCacheDevice.cpp b/netwerk/cache/nsDiskCacheDevice.cpp index 4fb009e4f579..6988fc3fe4d1 100644 --- a/netwerk/cache/nsDiskCacheDevice.cpp +++ b/netwerk/cache/nsDiskCacheDevice.cpp @@ -1008,6 +1008,7 @@ nsDiskCacheDevice::OpenDiskCache() // if we don't have a cache directory, create one and open it if (!exists) { + nsCacheService::MarkStartingFresh(); rv = mCacheDirectory->Create(nsIFile::DIRECTORY_TYPE, 0777); CACHE_LOG_PATH(PR_LOG_ALWAYS, "\ncreate cache directory: %s\n", mCacheDirectory); CACHE_LOG_ALWAYS(("mCacheDirectory->Create() = %x\n", rv)); diff --git a/toolkit/components/telemetry/TelemetryHistograms.h b/toolkit/components/telemetry/TelemetryHistograms.h index 83531f4f4ca7..0e48d7a0decb 100644 --- a/toolkit/components/telemetry/TelemetryHistograms.h +++ b/toolkit/components/telemetry/TelemetryHistograms.h @@ -208,6 +208,7 @@ HISTOGRAM(HTTP_DISK_CACHE_OVERHEAD, 1, 32000000, 100, EXPONENTIAL, "HTTP Disk ca HISTOGRAM(CACHE_LM_INCONSISTENT, 0, 1, 2, BOOLEAN, "Cache discovered inconsistent last-modified entry") HISTOGRAM(CACHE_SERVICE_LOCK_WAIT, 1, 10000, 10000, LINEAR, "Time spent waiting on the cache service lock (ms)") HISTOGRAM(CACHE_SERVICE_LOCK_WAIT_MAINTHREAD, 1, 10000, 10000, LINEAR, "Time spent waiting on the cache service lock on the main thread (ms)") +HISTOGRAM(DISK_CACHE_SMART_SIZE_USING_OLD_MAX, 0, 1, 2, BOOLEAN, "Whether we are using the old default cache smart size") #define CACHE_LOCK_HISTOGRAM(x) \ HISTOGRAM(CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_##x, 1, 10 * 1000, 50, EXPONENTIAL, "Time spent waiting on the cache service lock (ms) on the main thread in " #x) From b6646fc24eb2004eab22598c2f0954b82e56b51b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabrice=20Desr=C3=A9?= Date: Tue, 7 Aug 2012 15:56:46 -0700 Subject: [PATCH 072/169] Bug 780686 - DOMApplicationRegistry._cloneAppObject doesn't clone the `receipts` array - followup [r=fabrice] --- dom/apps/src/Webapps.jsm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dom/apps/src/Webapps.jsm b/dom/apps/src/Webapps.jsm index 8f998a681473..b19dd81de18b 100644 --- a/dom/apps/src/Webapps.jsm +++ b/dom/apps/src/Webapps.jsm @@ -274,7 +274,7 @@ let DOMApplicationRegistry = { let clone = { installOrigin: aApp.installOrigin, origin: aApp.origin, - receipts: JSON.parse(JSON.stringify(aApp.receipts)), + receipts: aApp.receipts ? JSON.parse(JSON.stringify(aApp.receipts)) : null, installTime: aApp.installTime, manifestURL: aApp.manifestURL, progress: aApp.progress || 0.0, From d7bf07283f6e5321e8b16a276bedc100a007773d Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Wed, 8 Aug 2012 10:26:04 +1200 Subject: [PATCH 073/169] Bug 780432 - Add experimental --enable-pulseaudio configure option. r=kinetik,khuey --HG-- extra : rebase_source : 9bf00787997d4ed465427e6570c5d937c1cb9ff4 --- config/system-headers | 1 + configure.in | 20 ++++++++++++++++++++ js/src/config/system-headers | 1 + media/libcubeb/src/Makefile.in | 6 ++++++ toolkit/library/Makefile.in | 6 ++++++ 5 files changed, 34 insertions(+) diff --git a/config/system-headers b/config/system-headers index 18bad22542bf..55fa60c83e1b 100644 --- a/config/system-headers +++ b/config/system-headers @@ -595,6 +595,7 @@ psap.h Pt.h pthread.h pthread_np.h +pulse/pulseaudio.h pwd.h Python.h QDOffscreen.h diff --git a/configure.in b/configure.in index aa7cf98947eb..576442b869fa 100644 --- a/configure.in +++ b/configure.in @@ -5550,6 +5550,26 @@ if test -n "$MOZ_SYDNEYAUDIO" -a "$OS_TARGET" = "Linux"; then AC_MSG_ERROR([Need alsa for Ogg, Wave or WebM decoding on Linux. Disable with --disable-ogg --disable-wave --disable-webm. (On Ubuntu, you might try installing the package libasound2-dev.)])]) fi +dnl ======================================================== +dnl = Enable PulseAudio +dnl ======================================================== + +MOZ_ARG_ENABLE_BOOL(pulseaudio, +[ --enable-pulseaudio Enable PulseAudio support (experimental)], +MOZ_PULSEAUDIO=1, +MOZ_PULSEAUDIO=) + +if test -n "$MOZ_PULSEAUDIO"; then + AC_DEFINE(MOZ_CUBEB) + PKG_CHECK_MODULES(MOZ_PULSEAUDIO, libpulse, , + [echo "$MOZ_PULSEAUDIO_PKG_ERRORS" + AC_MSG_ERROR([pulseaudio audio backend requires libpulse package])]) +fi + +AC_SUBST(MOZ_PULSEAUDIO) +AC_SUBST(MOZ_PULSEAUDIO_CFLAGS) +AC_SUBST(MOZ_PULSEAUDIO_LIBS) + dnl ======================================================== dnl = Enable GStreamer dnl ======================================================== diff --git a/js/src/config/system-headers b/js/src/config/system-headers index 18bad22542bf..55fa60c83e1b 100644 --- a/js/src/config/system-headers +++ b/js/src/config/system-headers @@ -595,6 +595,7 @@ psap.h Pt.h pthread.h pthread_np.h +pulse/pulseaudio.h pwd.h Python.h QDOffscreen.h diff --git a/media/libcubeb/src/Makefile.in b/media/libcubeb/src/Makefile.in index 9afca97489c2..3fa028de4fba 100644 --- a/media/libcubeb/src/Makefile.in +++ b/media/libcubeb/src/Makefile.in @@ -42,4 +42,10 @@ CSRCS = \ $(NULL) endif +ifdef MOZ_PULSEAUDIO +CSRCS = \ + cubeb_pulse.c \ + $(NULL) +endif + include $(topsrcdir)/config/rules.mk diff --git a/toolkit/library/Makefile.in b/toolkit/library/Makefile.in index 3141b2d2c06a..cd20833348b2 100644 --- a/toolkit/library/Makefile.in +++ b/toolkit/library/Makefile.in @@ -376,6 +376,12 @@ EXTRA_DSO_LDOPTS += $(MOZ_ALSA_LIBS) endif endif +ifdef MOZ_PULSEAUDIO +ifdef MOZ_CUBEB +EXTRA_DSO_LDOPTS += $(MOZ_PULSEAUDIO_LIBS) +endif +endif + ifdef HAVE_CLOCK_MONOTONIC EXTRA_DSO_LDOPTS += $(REALTIME_LIBS) endif From 9237dae01bfc094158a54d2b68b1447c180ba5ad Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Wed, 8 Aug 2012 10:27:44 +1200 Subject: [PATCH 074/169] Bug 780432 - Explicitly pass CFLAGS for ALSA and PulseAudio. r=kinetik --HG-- extra : rebase_source : 829d51b17390d44fa31b786408e632844ad12473 --- media/libcubeb/src/Makefile.in | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/media/libcubeb/src/Makefile.in b/media/libcubeb/src/Makefile.in index 3fa028de4fba..c3ab02239ed8 100644 --- a/media/libcubeb/src/Makefile.in +++ b/media/libcubeb/src/Makefile.in @@ -49,3 +49,8 @@ CSRCS = \ endif include $(topsrcdir)/config/rules.mk + +CFLAGS += \ + $(MOZ_ALSA_CFLAGS) \ + $(MOZ_PULSEAUDIO_CFLAGS) \ + $(NULL) From a9f15852356965e05c4ef39787768724a84839a3 Mon Sep 17 00:00:00 2001 From: Paul Adenot Date: Sun, 15 Jul 2012 10:57:41 -0700 Subject: [PATCH 075/169] Bug 774084 - Fix a crash in nsBuiltinDecoder::GetSeekable. r=kinetik --HG-- extra : rebase_source : f05e051cc9ab850381d138e944f2cc3ea5b3e2f7 --- content/media/nsBuiltinDecoder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/media/nsBuiltinDecoder.cpp b/content/media/nsBuiltinDecoder.cpp index c4527ba61e9c..6341ed112f2d 100644 --- a/content/media/nsBuiltinDecoder.cpp +++ b/content/media/nsBuiltinDecoder.cpp @@ -957,7 +957,7 @@ nsresult nsBuiltinDecoder::GetSeekable(nsTimeRanges* aSeekable) return NS_OK; } - if (mDecoderStateMachine->IsSeekableInBufferedRanges()) { + if (mDecoderStateMachine && mDecoderStateMachine->IsSeekableInBufferedRanges()) { return GetBuffered(aSeekable); } else { // The stream is not seekable using only buffered ranges, and is not From 8e8a009e3bf6be93331ccc2705253d4ed53ba63d Mon Sep 17 00:00:00 2001 From: Paul Adenot Date: Mon, 6 Aug 2012 10:27:55 -0700 Subject: [PATCH 076/169] Bug 778902 - When a video finished playing, "pause" should be fired, and |paused| should be true. r=cpearce --HG-- extra : rebase_source : 2866707bd6b61d0225952ff49b858011d79e04ed --- content/html/content/src/nsHTMLMediaElement.cpp | 2 ++ content/media/test/test_paused_after_ended.html | 9 ++++++++- content/media/test/test_replay_metadata.html | 1 + 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/content/html/content/src/nsHTMLMediaElement.cpp b/content/html/content/src/nsHTMLMediaElement.cpp index 47d696317b72..00efb17b87ac 100644 --- a/content/html/content/src/nsHTMLMediaElement.cpp +++ b/content/html/content/src/nsHTMLMediaElement.cpp @@ -2821,6 +2821,8 @@ void nsHTMLMediaElement::PlaybackEnded() return; } + Pause(); + FireTimeUpdate(false); DispatchAsyncEvent(NS_LITERAL_STRING("ended")); } diff --git a/content/media/test/test_paused_after_ended.html b/content/media/test/test_paused_after_ended.html index 61d72b18e89e..8b08d9436bb7 100644 --- a/content/media/test/test_paused_after_ended.html +++ b/content/media/test/test_paused_after_ended.html @@ -14,10 +14,16 @@ var manager = new MediaTestManager; function ended(evt) { var v = evt.target; - is(v.paused, false, v._name + " must not be paused after end"); + is(v.gotPause, true, "We should have received a \"pause\" event.") + is(v.paused, true, v._name + " must be paused after end"); manager.finished(v.token); } +function pause(evt) { + var v = evt.target; + v.gotPause = true; +} + function startTest(test, token) { var v = document.createElement('video'); v.token = token; @@ -31,6 +37,7 @@ function startTest(test, token) { v.play(); is(v.paused, false, v._name + " must not be paused after play"); + v.addEventListener("pause", pause, false); v.addEventListener("ended", ended, false); } diff --git a/content/media/test/test_replay_metadata.html b/content/media/test/test_replay_metadata.html index b0c7e0b48e07..c002e6ba6792 100644 --- a/content/media/test/test_replay_metadata.html +++ b/content/media/test/test_replay_metadata.html @@ -32,6 +32,7 @@ function seekStarted(evt) { function seekEnded(evt) { var v = evt.target; v._gotSeekEnded = true; + v.play(); } function loadedData(evt) { From 8616731bef919538342736daebcf7469c03f1bc9 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Tue, 7 Aug 2012 16:20:10 -0700 Subject: [PATCH 077/169] Bug 761806 - Support webapp uninstallation on Linux. r=myk --- toolkit/webapps/WebappsInstaller.jsm | 2 +- webapprt/gtk2/webapprt.cpp | 46 +++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/toolkit/webapps/WebappsInstaller.jsm b/toolkit/webapps/WebappsInstaller.jsm index f53796d5624f..6337ec5daa85 100644 --- a/toolkit/webapps/WebappsInstaller.jsm +++ b/toolkit/webapps/WebappsInstaller.jsm @@ -680,7 +680,7 @@ LinuxNativeApp.prototype = { this.installDir.append("." + this.uniqueName); this.iconFile = this.installDir.clone(); - this.iconFile.append(this.uniqueName + ".png"); + this.iconFile.append("icon.png"); this.webapprt = this.installDir.clone(); this.webapprt.append("webapprt-stub"); diff --git a/webapprt/gtk2/webapprt.cpp b/webapprt/gtk2/webapprt.cpp index 90b5bd90f5d8..c35bd40392ce 100644 --- a/webapprt/gtk2/webapprt.cpp +++ b/webapprt/gtk2/webapprt.cpp @@ -21,6 +21,7 @@ const char kAPP_INI[] = "application.ini"; const char kWEBAPP_INI[] = "webapp.ini"; +const char kWEBAPP_JSON[] = "webapp.json"; const char kWEBAPPRT_INI[] = "webapprt.ini"; const char kWEBAPPRT_PATH[] = "webapprt"; const char kAPP_ENV_VAR[] = "XUL_APP_FILE"; @@ -226,6 +227,41 @@ void CopyAndRelaunch(const char* firefoxDir, const char* curExePath) ErrorDialog("Couldn't execute the new webapprt-stub executable"); } +void RemoveApplication(const char* curExeDir, const char* profile) { + if (!isProfileOverridden) { + // Remove the desktop entry file. + char desktopEntryFilePath[MAXPATHLEN]; + + char* dataDir = getenv("XDG_DATA_HOME"); + + if (dataDir && *dataDir) { + snprintf(desktopEntryFilePath, MAXPATHLEN, "%s/applications/owa-%s.desktop", dataDir, profile); + } else { + char* home = getenv("HOME"); + snprintf(desktopEntryFilePath, MAXPATHLEN, "%s/.local/share/applications/owa-%s.desktop", home, profile); + } + + unlink(desktopEntryFilePath); + } + + // Remove the files from the installation directory. + char webAppIniPath[MAXPATHLEN]; + snprintf(webAppIniPath, MAXPATHLEN, "%s/%s", curExeDir, kWEBAPP_INI); + unlink(webAppIniPath); + + char curExePath[MAXPATHLEN]; + snprintf(curExePath, MAXPATHLEN, "%s/%s", curExeDir, kAPP_RT); + unlink(curExePath); + + char webAppJsonPath[MAXPATHLEN]; + snprintf(webAppJsonPath, MAXPATHLEN, "%s/%s", curExeDir, kWEBAPP_JSON); + unlink(webAppJsonPath); + + char iconPath[MAXPATHLEN]; + snprintf(iconPath, MAXPATHLEN, "%s/icon.png", curExeDir); + unlink(iconPath); +} + int main(int argc, char *argv[]) { pargc = &argc; @@ -240,10 +276,13 @@ int main(int argc, char *argv[]) char curExeDir[MAXPATHLEN]; GetDirFromPath(curExeDir, curExePath); + bool removeApp = false; for (int i = 1; i < argc; i++) { if (!strcmp(argv[i], "-profile")) { isProfileOverridden = true; - break; + } + else if (!strcmp(argv[i], "-remove")) { + removeApp = true; } } @@ -282,6 +321,11 @@ int main(int argc, char *argv[]) return 255; } + if (removeApp) { + RemoveApplication(curExeDir, profile); + return 0; + } + // Get the location of Firefox from our webapp.ini if (NS_FAILED(parser.GetString("WebappRT", "InstallDir", firefoxDir, MAXPATHLEN))) { ErrorDialog("Couldn't find your Firefox install directory."); From 9f556de8def7e37aa0b6bd51a5f870c002a1ce14 Mon Sep 17 00:00:00 2001 From: Gregor Wagner Date: Tue, 7 Aug 2012 16:22:24 -0700 Subject: [PATCH 078/169] Bug 779331 - Settings API: new permissions. r=mrbkap --- b2g/chrome/content/shell.js | 1 - dom/settings/SettingsManager.js | 22 ++++++------------- dom/settings/tests/test_settings_basics.html | 3 +-- .../geolocation/test_mozsettings.html | 3 +-- .../geolocation/test_mozsettingsWatch.html | 3 +-- 5 files changed, 10 insertions(+), 22 deletions(-) diff --git a/b2g/chrome/content/shell.js b/b2g/chrome/content/shell.js index e4f9c9dbf038..46ad352c2e44 100644 --- a/b2g/chrome/content/shell.js +++ b/b2g/chrome/content/shell.js @@ -54,7 +54,6 @@ function getContentWindow() { function addPermissions(urls) { let permissions = [ 'indexedDB-unlimited', 'webapps-manage', 'offline-app', 'pin-app', - 'websettings-read', 'websettings-readwrite', 'content-camera', 'wifi-manage', 'desktop-notification', 'geolocation', 'device-storage', 'alarms' ]; diff --git a/dom/settings/SettingsManager.js b/dom/settings/SettingsManager.js index 94a93fd31c0c..45a29e2e3612 100644 --- a/dom/settings/SettingsManager.js +++ b/dom/settings/SettingsManager.js @@ -144,7 +144,7 @@ SettingsLock.prototype = { throw Components.results.NS_ERROR_ABORT; } - if (this._settingsManager.hasReadPrivileges || this._settingsManager.hasReadWritePrivileges) { + if (this._settingsManager.hasPrivileges) { let req = Services.DOMRequest.createRequest(this._settingsManager._window); this._requests.enqueue({ request: req, intent:"get", name: aName }); this.createTransactionAndProcess(); @@ -161,7 +161,7 @@ SettingsLock.prototype = { throw Components.results.NS_ERROR_ABORT; } - if (this._settingsManager.hasReadWritePrivileges) { + if (this._settingsManager.hasPrivileges) { let req = Services.DOMRequest.createRequest(this._settingsManager._window); debug("send: " + JSON.stringify(aSettings)); this._requests.enqueue({request: req, intent: "set", settings: aSettings}); @@ -179,7 +179,7 @@ SettingsLock.prototype = { throw Components.results.NS_ERROR_ABORT; } - if (this._settingsManager.hasReadWritePrivileges) { + if (this._settingsManager.hasPrivileges) { let req = Services.DOMRequest.createRequest(this._settingsManager._window); this._requests.enqueue({ request: req, intent: "clear"}); this.createTransactionAndProcess(); @@ -227,7 +227,7 @@ SettingsManager.prototype = { }, set onsettingchange(aCallback) { - if (this.hasReadPrivileges || this.hasReadWritePrivileges) + if (this.hasPrivileges) this._onsettingchange = aCallback; else throw Components.results.NS_ERROR_NOT_IMPLEMENTED; @@ -317,17 +317,9 @@ SettingsManager.prototype = { let util = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils); this.innerWindowID = util.currentInnerWindowID; - let principal = aWindow.document.nodePrincipal; - let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager); - let readPerm = principal == secMan.getSystemPrincipal() - ? Ci.nsIPermissionManager.ALLOW_ACTION - : Services.perms.testExactPermissionFromPrincipal(principal, "websettings-read"); - let readwritePerm = principal == secMan.getSystemPrincipal() - ? Ci.nsIPermissionManager.ALLOW_ACTION - : Services.perms.testExactPermissionFromPrincipal(principal, "websettings-readwrite"); - this.hasReadPrivileges = readPerm == Ci.nsIPermissionManager.ALLOW_ACTION; - this.hasReadWritePrivileges = readwritePerm == Ci.nsIPermissionManager.ALLOW_ACTION; - debug("has read privileges :" + this.hasReadPrivileges + ", has read-write privileges: " + this.hasReadWritePrivileges); + let perm = Services.perms.testExactPermissionFromPrincipal(aWindow.document.nodePrincipal, "settings"); + this.hasPrivileges = perm == Ci.nsIPermissionManager.ALLOW_ACTION; + debug("has privileges :" + this.hasPrivileges); }, observe: function(aSubject, aTopic, aData) { diff --git a/dom/settings/tests/test_settings_basics.html b/dom/settings/tests/test_settings_basics.html index 6a5152cc399c..f7a3a99dddaa 100644 --- a/dom/settings/tests/test_settings_basics.html +++ b/dom/settings/tests/test_settings_basics.html @@ -24,8 +24,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id={678695} var comp = SpecialPowers.wrap(Components); comp.utils.import("resource://gre/modules/SettingsChangeNotifier.jsm"); SpecialPowers.setBoolPref("dom.mozSettings.enabled", true); -SpecialPowers.addPermission("websettings-read", true, document); -SpecialPowers.addPermission("websettings-readwrite", true, document); +SpecialPowers.addPermission("settings", true, document); function onUnwantedSuccess() { ok(false, "onUnwantedSuccess: shouldn't get here"); diff --git a/dom/tests/mochitest/geolocation/test_mozsettings.html b/dom/tests/mochitest/geolocation/test_mozsettings.html index 8e5fbe34e674..0f2371c324ac 100644 --- a/dom/tests/mochitest/geolocation/test_mozsettings.html +++ b/dom/tests/mochitest/geolocation/test_mozsettings.html @@ -39,8 +39,7 @@ force_prompt(true); var comp = SpecialPowers.wrap(Components); SpecialPowers.setBoolPref("dom.mozSettings.enabled", true); -SpecialPowers.addPermission("websettings-read", true, document); -SpecialPowers.addPermission("websettings-readwrite", true, document); +SpecialPowers.addPermission("settings", true, document); comp.utils.import("resource://gre/modules/SettingsChangeNotifier.jsm"); toggleGeolocationSetting(false, function() { diff --git a/dom/tests/mochitest/geolocation/test_mozsettingsWatch.html b/dom/tests/mochitest/geolocation/test_mozsettingsWatch.html index b7bda81cc1a5..35ebdd1aeb48 100644 --- a/dom/tests/mochitest/geolocation/test_mozsettingsWatch.html +++ b/dom/tests/mochitest/geolocation/test_mozsettingsWatch.html @@ -39,8 +39,7 @@ force_prompt(true); var comp = SpecialPowers.wrap(Components); SpecialPowers.setBoolPref("dom.mozSettings.enabled", true); -SpecialPowers.addPermission("websettings-read", true, document); -SpecialPowers.addPermission("websettings-readwrite", true, document); +SpecialPowers.addPermission("settings", true, document); comp.utils.import("resource://gre/modules/SettingsChangeNotifier.jsm"); toggleGeolocationSetting(false, function() { From 1b2c2dc75a062987f826ebb8100defa9eceb4435 Mon Sep 17 00:00:00 2001 From: Margaret Leibovic Date: Tue, 7 Aug 2012 11:20:11 -0700 Subject: [PATCH 079/169] Bug 778263 - Clean up SelectionHandler data when we bail in startSelection. r=mfinkle --- mobile/android/chrome/content/browser.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index cdcfefb1d4b8..19947abfd769 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -1683,13 +1683,14 @@ var SelectionHandler = { selectionController.wordMove(!this._isRTL, true); } catch(e) { // If we couldn't select the word at the given point, bail - Cu.reportError("Error selecting word: " + e); + this._cleanUp(); return; } // If there isn't an appropriate selection, bail if (!selection.rangeCount || !selection.getRangeAt(0) || !selection.toString().trim().length) { selection.collapseToStart(); + this._cleanUp(); return; } @@ -1838,13 +1839,17 @@ var SelectionHandler = { } } + this._cleanUp(); + + return selectedText; + }, + + _cleanUp: function sh_cleanUp() { this._view.removeEventListener("pagehide", this, false); this._view = null; this._target = null; this._isRTL = false; this.cache = null; - - return selectedText; }, _getViewOffset: function sh_getViewOffset() { From c09844be30f1e77ac549c917ee681ad673723b65 Mon Sep 17 00:00:00 2001 From: Paul Adenot Date: Tue, 7 Aug 2012 16:01:02 -0700 Subject: [PATCH 080/169] Bug 775319 - Determine the sample format at compile time for all media code. r=kinetik --HG-- extra : rebase_source : 4e8a2a4544895c9234ccd3992e1cafe82b8cf365 --- configure.in | 38 +++-- .../html/content/src/nsHTMLAudioElement.cpp | 3 +- content/media/MediaStreamGraph.cpp | 3 +- content/media/nsAudioStream.cpp | 138 +++++------------- content/media/nsAudioStream.h | 15 +- content/media/nsBuiltinDecoderReader.h | 6 +- .../media/nsBuiltinDecoderStateMachine.cpp | 2 +- dom/ipc/AudioParent.cpp | 4 +- 8 files changed, 75 insertions(+), 134 deletions(-) diff --git a/configure.in b/configure.in index 576442b869fa..b4ea87292084 100644 --- a/configure.in +++ b/configure.in @@ -4150,6 +4150,7 @@ MOZ_SPEEX_RESAMPLER=1 MOZ_CUBEB= MOZ_VORBIS= MOZ_TREMOR= +MOZ_FLOATING_POINT_AUDIO= MOZ_WAVE=1 MOZ_MEDIA= MOZ_OPUS=1 @@ -5199,6 +5200,24 @@ fi AC_SUBST(MOZ_WEBRTC) +dnl ======================================================== +dnl = Disable floating point audio. +dnl ======================================================== +MOZ_ARG_DISABLE_BOOL(floating-point, +[ --disable-floating-point Disable floating point audio], + MOZ_FLOATING_POINT_AUDIO=, + MOZ_FLOATING_POINT_AUDIO=1) + + +case "$target_cpu" in +arm*) +;; +*) + AC_DEFINE(MOZ_FLOATING_POINT_AUDIO) + MOZ_FLOATING_POINT_AUDIO=1 +;; +esac + dnl ======================================================== dnl = Enable Raw Codecs dnl ======================================================== @@ -5227,14 +5246,6 @@ if test -n "$MOZ_OGG"; then MOZ_SYDNEYAUDIO=1 MOZ_CUBEB=1 MOZ_MEDIA=1 - case "$target_cpu" in - arm*) - MOZ_TREMOR=1 - ;; - *) - MOZ_VORBIS=1 - ;; - esac dnl Checks for __attribute__(aligned()) directive AC_CACHE_CHECK([__attribute__ ((aligned ())) support], @@ -5364,14 +5375,11 @@ if test "$MOZ_WEBM"; then MOZ_SYDNEYAUDIO=1 MOZ_CUBEB=1 MOZ_MEDIA=1 - case "$target_cpu" in - arm*) - MOZ_TREMOR=1 - ;; - *) + if test -n "$MOZ_FLOATING_POINT_AUDIO"; then MOZ_VORBIS=1 - ;; - esac + else + MOZ_TREMOR=1 + fi fi if test -n "$MOZ_VP8" -a -z "$MOZ_NATIVE_LIBVPX"; then diff --git a/content/html/content/src/nsHTMLAudioElement.cpp b/content/html/content/src/nsHTMLAudioElement.cpp index 9a5ac2e87d9c..db373cea1cea 100644 --- a/content/html/content/src/nsHTMLAudioElement.cpp +++ b/content/html/content/src/nsHTMLAudioElement.cpp @@ -116,8 +116,7 @@ nsHTMLAudioElement::MozSetup(PRUint32 aChannels, PRUint32 aRate) } mAudioStream = nsAudioStream::AllocateStream(); - nsresult rv = mAudioStream->Init(aChannels, aRate, - nsAudioStream::FORMAT_FLOAT32); + nsresult rv = mAudioStream->Init(aChannels, aRate); if (NS_FAILED(rv)) { mAudioStream->Shutdown(); mAudioStream = nullptr; diff --git a/content/media/MediaStreamGraph.cpp b/content/media/MediaStreamGraph.cpp index e94c80cf659b..91ea202f19fc 100644 --- a/content/media/MediaStreamGraph.cpp +++ b/content/media/MediaStreamGraph.cpp @@ -1103,8 +1103,7 @@ MediaStreamGraphImpl::CreateOrDestroyAudioStream(GraphTime aAudioOutputStartTime aStream->mAudioPlaybackStartTime = aAudioOutputStartTime; aStream->mAudioOutput = nsAudioStream::AllocateStream(); aStream->mAudioOutput->Init(audio->GetChannels(), - track->GetRate(), - audio->GetFirstFrameFormat()); + track->GetRate()); } void diff --git a/content/media/nsAudioStream.cpp b/content/media/nsAudioStream.cpp index 118729c033f2..8b09234ae719 100644 --- a/content/media/nsAudioStream.cpp +++ b/content/media/nsAudioStream.cpp @@ -60,7 +60,7 @@ class nsNativeAudioStream : public nsAudioStream ~nsNativeAudioStream(); nsNativeAudioStream(); - nsresult Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat); + nsresult Init(PRInt32 aNumChannels, PRInt32 aRate); void Shutdown(); nsresult Write(const void* aBuf, PRUint32 aFrames); PRUint32 Available(); @@ -95,7 +95,7 @@ class nsRemotedAudioStream : public nsAudioStream nsRemotedAudioStream(); ~nsRemotedAudioStream(); - nsresult Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat); + nsresult Init(PRInt32 aNumChannels, PRInt32 aRate); void Shutdown(); nsresult Write(const void* aBuf, PRUint32 aFrames); PRUint32 Available(); @@ -422,11 +422,11 @@ nsNativeAudioStream::~nsNativeAudioStream() NS_IMPL_THREADSAFE_ISUPPORTS0(nsNativeAudioStream) -nsresult nsNativeAudioStream::Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat) +nsresult nsNativeAudioStream::Init(PRInt32 aNumChannels, PRInt32 aRate) { mRate = aRate; mChannels = aNumChannels; - mFormat = aFormat; + mFormat = MOZ_AUDIO_DATA_FORMAT; if (sa_stream_create_pcm(reinterpret_cast(&mAudioHandle), NULL, @@ -474,53 +474,28 @@ nsresult nsNativeAudioStream::Write(const void* aBuf, PRUint32 aFrames) if (s_data) { double scaled_volume = GetVolumeScale() * mVolume; - switch (mFormat) { - case FORMAT_U8: { - const PRUint8* buf = static_cast(aBuf); - PRInt32 volume = PRInt32((1 << 16) * scaled_volume); - for (PRUint32 i = 0; i < samples; ++i) { - s_data[i] = short(((PRInt32(buf[i]) - 128) * volume) >> 8); - } - break; - } - case FORMAT_S16_LE: { - const short* buf = static_cast(aBuf); - PRInt32 volume = PRInt32((1 << 16) * scaled_volume); - for (PRUint32 i = 0; i < samples; ++i) { - short s = buf[i]; -#if defined(IS_BIG_ENDIAN) - s = ((s & 0x00ff) << 8) | ((s & 0xff00) >> 8); -#endif - s_data[i] = short((PRInt32(s) * volume) >> 16); - } - break; - } - case FORMAT_FLOAT32: { - const float* buf = static_cast(aBuf); - for (PRUint32 i = 0; i < samples; ++i) { - float scaled_value = floorf(0.5 + 32768 * buf[i] * scaled_volume); - if (buf[i] < 0.0) { - s_data[i] = (scaled_value < -32768.0) ? - -32768 : - short(scaled_value); - } else { - s_data[i] = (scaled_value > 32767.0) ? - 32767 : - short(scaled_value); - } - } - break; + const SampleType* buf = static_cast(aBuf); + for (PRUint32 i = 0; i < samples; ++i) { + float scaled_value = floorf(0.5 + 32768 * buf[i] * scaled_volume); + if (buf[i] < 0.0) { + s_data[i] = (scaled_value < -32768.0) ? + -32768 : + short(scaled_value); + } else { + s_data[i] = (scaled_value > 32767.0) ? + 32767 : + short(scaled_value); } } + } - if (sa_stream_write(static_cast(mAudioHandle), - s_data.get(), - samples * sizeof(short)) != SA_SUCCESS) - { - PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsNativeAudioStream: sa_stream_write error")); - mInError = true; - return NS_ERROR_FAILURE; - } + if (sa_stream_write(static_cast(mAudioHandle), + s_data.get(), + samples * sizeof(short)) != SA_SUCCESS) + { + PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsNativeAudioStream: sa_stream_write error")); + mInError = true; + return NS_ERROR_FAILURE; } return NS_OK; } @@ -644,26 +619,12 @@ NS_IMPL_THREADSAFE_ISUPPORTS0(nsRemotedAudioStream) nsresult nsRemotedAudioStream::Init(PRInt32 aNumChannels, - PRInt32 aRate, - SampleFormat aFormat) + PRInt32 aRate) { mRate = aRate; mChannels = aNumChannels; - mFormat = aFormat; - - switch (mFormat) { - case FORMAT_U8: { - mBytesPerFrame = sizeof(PRUint8) * mChannels; - break; - } - case FORMAT_S16_LE: { - mBytesPerFrame = sizeof(short) * mChannels; - break; - } - case FORMAT_FLOAT32: { - mBytesPerFrame = sizeof(float) * mChannels; - } - } + mFormat = MOZ_AUDIO_DATA_FORMAT; + mBytesPerFrame = sizeof(SampleType) * mChannels; nsCOMPtr event = new AudioInitEvent(this); NS_DispatchToMainThread(event, NS_DISPATCH_SYNC); @@ -861,7 +822,7 @@ class nsBufferedAudioStream : public nsAudioStream nsBufferedAudioStream(); ~nsBufferedAudioStream(); - nsresult Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat); + nsresult Init(PRInt32 aNumChannels, PRInt32 aRate); void Shutdown(); nsresult Write(const void* aBuf, PRUint32 aFrames); PRUint32 Available(); @@ -963,7 +924,7 @@ nsBufferedAudioStream::~nsBufferedAudioStream() NS_IMPL_THREADSAFE_ISUPPORTS0(nsBufferedAudioStream) nsresult -nsBufferedAudioStream::Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat) +nsBufferedAudioStream::Init(PRInt32 aNumChannels, PRInt32 aRate) { cubeb* cubebContext = GetCubebContext(); @@ -973,23 +934,13 @@ nsBufferedAudioStream::Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aF mRate = aRate; mChannels = aNumChannels; - mFormat = aFormat; + mFormat = MOZ_AUDIO_DATA_FORMAT; cubeb_stream_params params; params.rate = aRate; params.channels = aNumChannels; - switch (aFormat) { - case FORMAT_S16_LE: - params.format = CUBEB_SAMPLE_S16LE; - mBytesPerFrame = sizeof(short) * aNumChannels; - break; - case FORMAT_FLOAT32: - params.format = CUBEB_SAMPLE_FLOAT32NE; - mBytesPerFrame = sizeof(float) * aNumChannels; - break; - default: - return NS_ERROR_FAILURE; - } + params.format = CUBEB_SAMPLE_FLOAT32NE; + mBytesPerFrame = sizeof(float) * aNumChannels; { cubeb_stream* stream; @@ -1221,29 +1172,10 @@ nsBufferedAudioStream::DataCallback(void* aBuffer, long aFrames) output += input_size[i]; } else { // Adjust volume as each sample is copied out. - switch (mFormat) { - case FORMAT_S16_LE: { - PRInt32 volume = PRInt32(1 << 16) * scaled_volume; - - const short* src = static_cast(input[i]); - short* dst = reinterpret_cast(output); - for (PRUint32 j = 0; j < input_size[i] / (mBytesPerFrame / mChannels); ++j) { - dst[j] = short((PRInt32(src[j]) * volume) >> 16); - } - output += input_size[i]; - break; - } - case FORMAT_FLOAT32: { - const float* src = static_cast(input[i]); - float* dst = reinterpret_cast(output); - for (PRUint32 j = 0; j < input_size[i] / (mBytesPerFrame / mChannels); ++j) { - dst[j] = src[j] * scaled_volume; - } - output += input_size[i]; - break; - } - default: - return -1; + const float* src = static_cast(input[i]); + float* dst = reinterpret_cast(output); + for (PRUint32 j = 0; j < input_size[i] / (mBytesPerFrame / mChannels); ++j) { + dst[j] = src[j] * scaled_volume; } } } diff --git a/content/media/nsAudioStream.h b/content/media/nsAudioStream.h index b1d63fc8bb7e..ff3b136d5056 100644 --- a/content/media/nsAudioStream.h +++ b/content/media/nsAudioStream.h @@ -11,6 +11,14 @@ #include "nsIThread.h" #include "nsAutoPtr.h" +#ifndef MOZ_FLOATING_POINT_AUDIO +#define MOZ_AUDIO_DATA_FORMAT (nsAudioStream::FORMAT_S16_LE) +typedef short SampleType; +#else +#define MOZ_AUDIO_DATA_FORMAT (nsAudioStream::FORMAT_FLOAT32) +typedef float SampleType; +#endif + // Access to a single instance of this class must be synchronized by // callers, or made from a single thread. One exception is that access to // GetPosition, GetPositionInFrames, SetVolume, and Get{Rate,Channels,Format} @@ -28,8 +36,7 @@ public: nsAudioStream() : mRate(0), - mChannels(0), - mFormat(FORMAT_S16_LE) + mChannels(0) {} virtual ~nsAudioStream(); @@ -56,7 +63,7 @@ public: // (22050Hz, 44100Hz, etc). // Unsafe to call with a monitor held due to synchronous event execution // on the main thread, which may attempt to acquire any held monitor. - virtual nsresult Init(PRInt32 aNumChannels, PRInt32 aRate, SampleFormat aFormat) = 0; + virtual nsresult Init(PRInt32 aNumChannels, PRInt32 aRate) = 0; // Closes the stream. All future use of the stream is an error. // Unsafe to call with a monitor held due to synchronous event execution @@ -106,7 +113,7 @@ public: int GetRate() { return mRate; } int GetChannels() { return mChannels; } - SampleFormat GetFormat() { return mFormat; } + SampleFormat GetFormat() { return MOZ_AUDIO_DATA_FORMAT; } protected: nsCOMPtr mAudioPlaybackThread; diff --git a/content/media/nsBuiltinDecoderReader.h b/content/media/nsBuiltinDecoderReader.h index 39bbc0cc19ef..c3683e333d83 100644 --- a/content/media/nsBuiltinDecoderReader.h +++ b/content/media/nsBuiltinDecoderReader.h @@ -52,12 +52,11 @@ public: bool mHasVideo; }; -#ifdef MOZ_TREMOR +#ifndef MOZ_FLOATING_POINT_AUDIO #include typedef ogg_int32_t VorbisPCMValue; typedef short AudioDataValue; -#define MOZ_AUDIO_DATA_FORMAT (nsAudioStream::FORMAT_S16_LE) #define MOZ_CLIP_TO_15(x) ((x)<-32768?-32768:(x)<=32767?(x):32767) // Convert the output of vorbis_synthesis_pcmout to a AudioDataValue #define MOZ_CONVERT_VORBIS_SAMPLE(x) \ @@ -66,12 +65,11 @@ typedef short AudioDataValue; #define MOZ_CONVERT_AUDIO_SAMPLE(x) ((x)*(1.F/32768)) #define MOZ_SAMPLE_TYPE_S16LE 1 -#else /*MOZ_VORBIS*/ +#else /* MOZ_FLOATING_POINT_AUDIO == 1*/ typedef float VorbisPCMValue; typedef float AudioDataValue; -#define MOZ_AUDIO_DATA_FORMAT (nsAudioStream::FORMAT_FLOAT32) #define MOZ_CONVERT_VORBIS_SAMPLE(x) (x) #define MOZ_CONVERT_AUDIO_SAMPLE(x) (x) #define MOZ_SAMPLE_TYPE_FLOAT32 1 diff --git a/content/media/nsBuiltinDecoderStateMachine.cpp b/content/media/nsBuiltinDecoderStateMachine.cpp index 2fd392cf9c37..55a57f03a931 100644 --- a/content/media/nsBuiltinDecoderStateMachine.cpp +++ b/content/media/nsBuiltinDecoderStateMachine.cpp @@ -1008,7 +1008,7 @@ void nsBuiltinDecoderStateMachine::AudioLoop() // are unsafe to call with the decoder monitor held are documented as such // in nsAudioStream.h. nsRefPtr audioStream = nsAudioStream::AllocateStream(); - audioStream->Init(channels, rate, MOZ_AUDIO_DATA_FORMAT); + audioStream->Init(channels, rate); { // We must hold the monitor while setting mAudioStream or whenever we query diff --git a/dom/ipc/AudioParent.cpp b/dom/ipc/AudioParent.cpp index ce10c45d1a7a..386ee79c35df 100644 --- a/dom/ipc/AudioParent.cpp +++ b/dom/ipc/AudioParent.cpp @@ -297,9 +297,7 @@ AudioParent::AudioParent(PRInt32 aNumChannels, PRInt32 aRate, PRInt32 aFormat) { mStream = nsAudioStream::AllocateStream(); NS_ASSERTION(mStream, "AudioStream allocation failed."); - if (NS_FAILED(mStream->Init(aNumChannels, - aRate, - (nsAudioStream::SampleFormat) aFormat))) { + if (NS_FAILED(mStream->Init(aNumChannels, aRate))) { NS_WARNING("AudioStream initialization failed."); mStream = nullptr; return; From e1de846b70a9455229e0282da89b92eb1c984479 Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Tue, 7 Aug 2012 16:29:32 -0700 Subject: [PATCH 081/169] Bug 778382: Don't put anonymous sockets in the PipeMap because they can collide. r=bent --- ipc/chromium/src/chrome/common/ipc_channel_posix.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ipc/chromium/src/chrome/common/ipc_channel_posix.cc b/ipc/chromium/src/chrome/common/ipc_channel_posix.cc index bd866eec8def..b86c83279962 100644 --- a/ipc/chromium/src/chrome/common/ipc_channel_posix.cc +++ b/ipc/chromium/src/chrome/common/ipc_channel_posix.cc @@ -336,7 +336,9 @@ bool Channel::ChannelImpl::CreatePipe(const std::wstring& channel_id, pipe_ = pipe_fds[0]; client_pipe_ = pipe_fds[1]; - Singleton()->Insert(pipe_name_, client_pipe_); + if (pipe_name_.length()) { + Singleton()->Insert(pipe_name_, client_pipe_); + } } else { pipe_ = ChannelNameToClientFD(pipe_name_); DCHECK(pipe_ > 0); From 97d7b479ffca71982830605472b7c57661068be7 Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Tue, 7 Aug 2012 16:29:32 -0700 Subject: [PATCH 082/169] Bug 774131, part 1: Refactor GeckoChildProcessHost to use a state enum and eagerly create a ProcessHandle. r=bent --- ipc/glue/GeckoChildProcessHost.cpp | 51 +++++++++++++++++++++--------- ipc/glue/GeckoChildProcessHost.h | 20 ++++++++++-- 2 files changed, 54 insertions(+), 17 deletions(-) diff --git a/ipc/glue/GeckoChildProcessHost.cpp b/ipc/glue/GeckoChildProcessHost.cpp index ced21cb57435..b09f1153adaa 100644 --- a/ipc/glue/GeckoChildProcessHost.cpp +++ b/ipc/glue/GeckoChildProcessHost.cpp @@ -79,8 +79,7 @@ GeckoChildProcessHost::GeckoChildProcessHost(GeckoProcessType aProcessType, : ChildProcessHost(RENDER_PROCESS), // FIXME/cjones: we should own this enum mProcessType(aProcessType), mMonitor("mozilla.ipc.GeckChildProcessHost.mMonitor"), - mLaunched(false), - mChannelInitialized(false), + mProcessState(CREATING_CHANNEL), mDelegate(aDelegate), mChildProcessHandle(0) #if defined(MOZ_WIDGET_COCOA) @@ -290,7 +289,7 @@ GeckoChildProcessHost::SyncLaunch(std::vector aExtraOpts, int aTime // We'll receive several notifications, we need to exit when we // have either successfully launched or have timed out. - while (!mLaunched) { + while (mProcessState < PROCESS_CONNECTED) { lock.Wait(timeoutTicks); if (timeoutTicks != PR_INTERVAL_NO_TIMEOUT) { @@ -304,7 +303,7 @@ GeckoChildProcessHost::SyncLaunch(std::vector aExtraOpts, int aTime } } - return mLaunched; + return mProcessState == PROCESS_CONNECTED; } bool @@ -329,7 +328,7 @@ GeckoChildProcessHost::AsyncLaunch(std::vector aExtraOpts) // This may look like the sync launch wait, but we only delay as // long as it takes to create the channel. MonitorAutoLock lock(mMonitor); - while (!mChannelInitialized) { + while (mProcessState < CHANNEL_INITIALIZED) { lock.Wait(); } @@ -342,7 +341,7 @@ GeckoChildProcessHost::InitializeChannel() CreateChannel(); MonitorAutoLock lock(mMonitor); - mChannelInitialized = true; + mProcessState = CHANNEL_INITIALIZED; lock.Notify(); } @@ -395,8 +394,6 @@ GeckoChildProcessHost::PerformAsyncLaunch(std::vector aExtraOpts, b bool GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector& aExtraOpts, base::ProcessArchitecture arch) { - // FIXME/cjones: make this work from non-IO threads, too - // We rely on the fact that InitializeChannel() has already been processed // on the IO thread before this point is reached. if (!GetChannel()) { @@ -684,26 +681,50 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector& aExt #endif if (!process) { + MonitorAutoLock lock(mMonitor); + mProcessState = PROCESS_ERROR; + lock.Notify(); return false; } + // NB: on OS X, we block much longer than we need to in order to + // reach this call, waiting for the child process's task_t. The + // best way to fix that is to refactor this file, hard. SetHandle(process); #if defined(MOZ_WIDGET_COCOA) mChildTask = child_task; #endif + OpenPrivilegedHandle(base::GetProcId(process)); + { + MonitorAutoLock lock(mMonitor); + mProcessState = PROCESS_CREATED; + lock.Notify(); + } + return true; } +void +GeckoChildProcessHost::OpenPrivilegedHandle(base::ProcessId aPid) +{ + if (mChildProcessHandle) { + MOZ_ASSERT(aPid == base::GetProcId(mChildProcessHandle)); + return; + } + if (!base::OpenPrivilegedProcessHandle(aPid, &mChildProcessHandle)) { + NS_RUNTIMEABORT("can't open handle to child process"); + } +} + void GeckoChildProcessHost::OnChannelConnected(int32 peer_pid) { - MonitorAutoLock lock(mMonitor); - mLaunched = true; - - if (!base::OpenPrivilegedProcessHandle(peer_pid, &mChildProcessHandle)) - NS_RUNTIMEABORT("can't open handle to child process"); - - lock.Notify(); + OpenPrivilegedHandle(peer_pid); + { + MonitorAutoLock lock(mMonitor); + mProcessState = PROCESS_CONNECTED; + lock.Notify(); + } } void diff --git a/ipc/glue/GeckoChildProcessHost.h b/ipc/glue/GeckoChildProcessHost.h index e855c021efc4..c6af88fca78d 100644 --- a/ipc/glue/GeckoChildProcessHost.h +++ b/ipc/glue/GeckoChildProcessHost.h @@ -76,9 +76,23 @@ public: protected: GeckoProcessType mProcessType; Monitor mMonitor; - bool mLaunched; - bool mChannelInitialized; FilePath mProcessPath; + // This value must be accessed while holding mMonitor. + enum { + // This object has been constructed, but the OS process has not + // yet. + CREATING_CHANNEL = 0, + // The IPC channel for our subprocess has been created, but the OS + // process has still not been created. + CHANNEL_INITIALIZED, + // The OS process has been created, but it hasn't yet connected to + // our IPC channel. + PROCESS_CREATED, + // The process is launched and connected to our IPC channel. All + // is well. + PROCESS_CONNECTED, + PROCESS_ERROR + } mProcessState; static PRInt32 mChildCounter; @@ -105,6 +119,8 @@ private: bool PerformAsyncLaunchInternal(std::vector& aExtraOpts, base::ProcessArchitecture arch); + void OpenPrivilegedHandle(base::ProcessId aPid); + // In between launching the subprocess and handing off its IPC // channel, there's a small window of time in which *we* might still // be the channel listener, and receive messages. That's bad From a7acbe1bfe5d3c75fa99a8867f6a0bc027bc9856 Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Tue, 7 Aug 2012 16:29:32 -0700 Subject: [PATCH 083/169] Bug 774131, part 2: Add GeckoChildProcessHost::LaunchAndWaitForProcessHandle() to do that, use it in ContentParent, and share more process-launching code. r=bent --- dom/ipc/ContentParent.cpp | 10 ++---- ipc/glue/GeckoChildProcessHost.cpp | 54 ++++++++++++++++++++---------- ipc/glue/GeckoChildProcessHost.h | 31 +++++++++++++++-- 3 files changed, 67 insertions(+), 28 deletions(-) diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index f18953ce94ed..5be7c24be125 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -489,13 +489,9 @@ ContentParent::ContentParent(const nsAString& aAppManifestURL) bool useOffMainThreadCompositing = !!CompositorParent::CompositorLoop(); if (useOffMainThreadCompositing) { - // FIXME. Oh please fixme. Somehow. - // - // We need the child process's ProcessHandle to do - // PCompositor::Open() below (on win32 ... sigh). We don't - // get that until onconnect, but that's too late to open the - // compositor channel below. - mSubprocess->SyncLaunch(); + // We need the subprocess's ProcessHandle to create the + // PCompositor channel below. Block just until we have that. + mSubprocess->LaunchAndWaitForProcessHandle(); } else { mSubprocess->AsyncLaunch(); } diff --git a/ipc/glue/GeckoChildProcessHost.cpp b/ipc/glue/GeckoChildProcessHost.cpp index b09f1153adaa..aa21991fb5d9 100644 --- a/ipc/glue/GeckoChildProcessHost.cpp +++ b/ipc/glue/GeckoChildProcessHost.cpp @@ -238,6 +238,20 @@ uint32 GeckoChildProcessHost::GetSupportedArchitecturesForProcessType(GeckoProce return base::GetCurrentProcessArchitecture(); } +void +GeckoChildProcessHost::PrepareLaunch() +{ +#ifdef MOZ_CRASHREPORTER + if (CrashReporter::GetEnabled()) { + CrashReporter::OOPInit(); + } +#endif + +#ifdef XP_WIN + InitWindowsGroupID(); +#endif +} + #ifdef XP_WIN void GeckoChildProcessHost::InitWindowsGroupID() { @@ -262,15 +276,7 @@ void GeckoChildProcessHost::InitWindowsGroupID() bool GeckoChildProcessHost::SyncLaunch(std::vector aExtraOpts, int aTimeoutMs, base::ProcessArchitecture arch) { -#ifdef MOZ_CRASHREPORTER - if (CrashReporter::GetEnabled()) { - CrashReporter::OOPInit(); - } -#endif - -#ifdef XP_WIN - InitWindowsGroupID(); -#endif + PrepareLaunch(); PRIntervalTime timeoutTicks = (aTimeoutMs > 0) ? PR_MillisecondsToInterval(aTimeoutMs) : PR_INTERVAL_NO_TIMEOUT; @@ -309,15 +315,7 @@ GeckoChildProcessHost::SyncLaunch(std::vector aExtraOpts, int aTime bool GeckoChildProcessHost::AsyncLaunch(std::vector aExtraOpts) { -#ifdef MOZ_CRASHREPORTER - if (CrashReporter::GetEnabled()) { - CrashReporter::OOPInit(); - } -#endif - -#ifdef XP_WIN - InitWindowsGroupID(); -#endif + PrepareLaunch(); MessageLoop* ioLoop = XRE_GetIOMessageLoop(); ioLoop->PostTask(FROM_HERE, @@ -335,6 +333,26 @@ GeckoChildProcessHost::AsyncLaunch(std::vector aExtraOpts) return true; } +bool +GeckoChildProcessHost::LaunchAndWaitForProcessHandle(StringVector aExtraOpts) +{ + PrepareLaunch(); + + MessageLoop* ioLoop = XRE_GetIOMessageLoop(); + ioLoop->PostTask(FROM_HERE, + NewRunnableMethod(this, + &GeckoChildProcessHost::PerformAsyncLaunch, + aExtraOpts, base::GetCurrentProcessArchitecture())); + + MonitorAutoLock lock(mMonitor); + while (mProcessState < PROCESS_CREATED) { + lock.Wait(); + } + MOZ_ASSERT(mProcessState == PROCESS_ERROR || mChildProcessHandle); + + return mProcessState < PROCESS_ERROR; +} + void GeckoChildProcessHost::InitializeChannel() { diff --git a/ipc/glue/GeckoChildProcessHost.h b/ipc/glue/GeckoChildProcessHost.h index c6af88fca78d..4c24ae427eea 100644 --- a/ipc/glue/GeckoChildProcessHost.h +++ b/ipc/glue/GeckoChildProcessHost.h @@ -23,6 +23,7 @@ class GeckoChildProcessHost : public ChildProcessHost { protected: typedef mozilla::Monitor Monitor; + typedef std::vector StringVector; public: typedef base::ProcessHandle ProcessHandle; @@ -36,11 +37,33 @@ public: static uint32 GetSupportedArchitecturesForProcessType(GeckoProcessType type); - bool SyncLaunch(std::vector aExtraOpts=std::vector(), + // Block until the IPC channel for our subprocess is initialized, + // but no longer. The child process may or may not have been + // created when this method returns. + bool AsyncLaunch(StringVector aExtraOpts=StringVector()); + + // Block until the IPC channel for our subprocess is initialized and + // the OS process is created. The subprocess may or may not have + // connected back to us when this method returns. + // + // NB: on POSIX, this method is relatively cheap, and doesn't + // require disk IO. On win32 however, it requires at least the + // analogue of stat(). This difference induces a semantic + // difference in this method: on POSIX, when we return, we know the + // subprocess has been created, but we don't know whether its + // executable image can be loaded. On win32, we do know that when + // we return. But we don't know if dynamic linking succeeded on + // either platform. + bool LaunchAndWaitForProcessHandle(StringVector aExtraOpts=StringVector()); + + // Block until the child process has been created and it connects to + // the IPC channel, meaning it's fully initialized. (Or until an + // error occurs.) + bool SyncLaunch(StringVector aExtraOpts=StringVector(), int32 timeoutMs=0, base::ProcessArchitecture arch=base::GetCurrentProcessArchitecture()); - bool AsyncLaunch(std::vector aExtraOpts=std::vector()); - bool PerformAsyncLaunch(std::vector aExtraOpts=std::vector(), + + bool PerformAsyncLaunch(StringVector aExtraOpts=StringVector(), base::ProcessArchitecture arch=base::GetCurrentProcessArchitecture()); virtual void OnChannelConnected(int32 peer_pid); @@ -96,6 +119,8 @@ protected: static PRInt32 mChildCounter; + void PrepareLaunch(); + #ifdef XP_WIN void InitWindowsGroupID(); nsString mGroupId; From 9959cd6296e8f788bafb3d8db5c45b067f463ecf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabrice=20Desr=C3=A9?= Date: Tue, 7 Aug 2012 16:41:41 -0700 Subject: [PATCH 084/169] # User Timothy Guan-tin Chien Bug 780487 - [b2g] All |oveflow:hidden| became scrollable, r=roc --- .../BrowserElementScrolling.js | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/dom/browser-element/BrowserElementScrolling.js b/dom/browser-element/BrowserElementScrolling.js index c07a759daf16..c17f27daddaa 100644 --- a/dom/browser-element/BrowserElementScrolling.js +++ b/dom/browser-element/BrowserElementScrolling.js @@ -117,12 +117,26 @@ const ContentPanning = { let nodeContent = node.ownerDocument.defaultView; while (!(node instanceof Ci.nsIDOMHTMLBodyElement)) { - if (node.scrollHeight > node.clientHeight || - node.scrollWidth > node.clientWidth || - ('scrollLeftMax' in node && node.scrollLeftMax > 0) || - ('scrollTopMax' in node && node.scrollTopMax > 0)) { + let style = nodeContent.getComputedStyle(node, null); + + let overflow = [style.getPropertyValue('overflow'), + style.getPropertyValue('overflow-x'), + style.getPropertyValue('overflow-y')]; + + let rect = node.getBoundingClientRect(); + let isAuto = (overflow.indexOf('auto') != -1 && + (rect.height < node.scrollHeight || + rect.width < node.scrollWidth)); + + let isScroll = (overflow.indexOf('scroll') != -1); + + let isScrollableTextarea = (node.tagName == 'TEXTAREA' && + (node.scrollHeight > node.clientHeight || + node.scrollWidth > node.clientWidth || + ('scrollLeftMax' in node && node.scrollLeftMax > 0) || + ('scrollTopMax' in node && node.scrollTopMax > 0))); + if (isScroll || isAuto || isScrollableTextarea) return [node, this._generateCallback(node)]; - } node = node.parentNode; } From 0ff92e380888630a0059d2852cd312936795ac90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabrice=20Desr=C3=A9?= Date: Tue, 7 Aug 2012 16:44:08 -0700 Subject: [PATCH 085/169] Backed out changeset c99709de566d --- .../BrowserElementScrolling.js | 24 ++++--------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/dom/browser-element/BrowserElementScrolling.js b/dom/browser-element/BrowserElementScrolling.js index c17f27daddaa..c07a759daf16 100644 --- a/dom/browser-element/BrowserElementScrolling.js +++ b/dom/browser-element/BrowserElementScrolling.js @@ -117,26 +117,12 @@ const ContentPanning = { let nodeContent = node.ownerDocument.defaultView; while (!(node instanceof Ci.nsIDOMHTMLBodyElement)) { - let style = nodeContent.getComputedStyle(node, null); - - let overflow = [style.getPropertyValue('overflow'), - style.getPropertyValue('overflow-x'), - style.getPropertyValue('overflow-y')]; - - let rect = node.getBoundingClientRect(); - let isAuto = (overflow.indexOf('auto') != -1 && - (rect.height < node.scrollHeight || - rect.width < node.scrollWidth)); - - let isScroll = (overflow.indexOf('scroll') != -1); - - let isScrollableTextarea = (node.tagName == 'TEXTAREA' && - (node.scrollHeight > node.clientHeight || - node.scrollWidth > node.clientWidth || - ('scrollLeftMax' in node && node.scrollLeftMax > 0) || - ('scrollTopMax' in node && node.scrollTopMax > 0))); - if (isScroll || isAuto || isScrollableTextarea) + if (node.scrollHeight > node.clientHeight || + node.scrollWidth > node.clientWidth || + ('scrollLeftMax' in node && node.scrollLeftMax > 0) || + ('scrollTopMax' in node && node.scrollTopMax > 0)) { return [node, this._generateCallback(node)]; + } node = node.parentNode; } From 66f94ede56495346406ae00e6435d299fb5dd789 Mon Sep 17 00:00:00 2001 From: Timothy Guan-tin Chien Date: Tue, 7 Aug 2012 16:46:55 -0700 Subject: [PATCH 086/169] Bug 780487 - [b2g] All |oveflow:hidden| became scrollable, r=roc --- .../BrowserElementScrolling.js | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/dom/browser-element/BrowserElementScrolling.js b/dom/browser-element/BrowserElementScrolling.js index c07a759daf16..c17f27daddaa 100644 --- a/dom/browser-element/BrowserElementScrolling.js +++ b/dom/browser-element/BrowserElementScrolling.js @@ -117,12 +117,26 @@ const ContentPanning = { let nodeContent = node.ownerDocument.defaultView; while (!(node instanceof Ci.nsIDOMHTMLBodyElement)) { - if (node.scrollHeight > node.clientHeight || - node.scrollWidth > node.clientWidth || - ('scrollLeftMax' in node && node.scrollLeftMax > 0) || - ('scrollTopMax' in node && node.scrollTopMax > 0)) { + let style = nodeContent.getComputedStyle(node, null); + + let overflow = [style.getPropertyValue('overflow'), + style.getPropertyValue('overflow-x'), + style.getPropertyValue('overflow-y')]; + + let rect = node.getBoundingClientRect(); + let isAuto = (overflow.indexOf('auto') != -1 && + (rect.height < node.scrollHeight || + rect.width < node.scrollWidth)); + + let isScroll = (overflow.indexOf('scroll') != -1); + + let isScrollableTextarea = (node.tagName == 'TEXTAREA' && + (node.scrollHeight > node.clientHeight || + node.scrollWidth > node.clientWidth || + ('scrollLeftMax' in node && node.scrollLeftMax > 0) || + ('scrollTopMax' in node && node.scrollTopMax > 0))); + if (isScroll || isAuto || isScrollableTextarea) return [node, this._generateCallback(node)]; - } node = node.parentNode; } From fed01c4c704be03e8f308259b8ac7d024b5f92ba Mon Sep 17 00:00:00 2001 From: Michal Novotny Date: Wed, 8 Aug 2012 02:06:06 +0200 Subject: [PATCH 087/169] Bug 779461 - Do not transfer the ownership of the key string from nsCacheRequest to nsCacheEntry, r=honzab --- netwerk/cache/nsCacheEntry.cpp | 22 ++++++++-------------- netwerk/cache/nsCacheEntry.h | 8 ++++---- netwerk/cache/nsCacheRequest.h | 5 ++--- netwerk/cache/nsCacheService.cpp | 21 ++++++++------------- 4 files changed, 22 insertions(+), 34 deletions(-) diff --git a/netwerk/cache/nsCacheEntry.cpp b/netwerk/cache/nsCacheEntry.cpp index 7d83e69af136..e98a021928b8 100644 --- a/netwerk/cache/nsCacheEntry.cpp +++ b/netwerk/cache/nsCacheEntry.cpp @@ -20,7 +20,7 @@ using namespace mozilla; -nsCacheEntry::nsCacheEntry(nsCString * key, +nsCacheEntry::nsCacheEntry(const nsACString & key, bool streamBased, nsCacheStoragePolicy storagePolicy) : mKey(key), @@ -50,7 +50,6 @@ nsCacheEntry::nsCacheEntry(nsCString * key, nsCacheEntry::~nsCacheEntry() { MOZ_COUNT_DTOR(nsCacheEntry); - delete mKey; if (mData) nsCacheService::ReleaseObject_Locked(mData, mThread); @@ -64,14 +63,10 @@ nsCacheEntry::Create( const char * key, nsCacheDevice * device, nsCacheEntry ** result) { - nsCString* newKey = new nsCString(key); - if (!newKey) return NS_ERROR_OUT_OF_MEMORY; - - nsCacheEntry* entry = new nsCacheEntry(newKey, streamBased, storagePolicy); - if (!entry) { delete newKey; return NS_ERROR_OUT_OF_MEMORY; } - + nsCacheEntry* entry = new nsCacheEntry(nsCString(key), + streamBased, + storagePolicy); entry->SetCacheDevice(device); - *result = entry; return NS_OK; } @@ -142,7 +137,6 @@ nsCacheEntry::RequestAccess(nsCacheRequest * request, nsCacheAccessMode *accessG if (!IsInitialized()) { // brand new, unbound entry - request->mKey = nullptr; // steal ownership of the key string if (request->IsStreamBased()) MarkStreamBased(); MarkInitialized(); @@ -449,7 +443,7 @@ nsCacheEntryHashTable::AddEntry( nsCacheEntry *cacheEntry) if (!initialized) return NS_ERROR_NOT_INITIALIZED; if (!cacheEntry) return NS_ERROR_NULL_POINTER; - hashEntry = PL_DHashTableOperate(&table, cacheEntry->mKey, PL_DHASH_ADD); + hashEntry = PL_DHashTableOperate(&table, &(cacheEntry->mKey), PL_DHASH_ADD); #ifndef DEBUG_dougt NS_ASSERTION(((nsCacheEntryHashTableEntry *)hashEntry)->cacheEntry == 0, "### nsCacheEntryHashTable::AddEntry - entry already used"); @@ -470,10 +464,10 @@ nsCacheEntryHashTable::RemoveEntry( nsCacheEntry *cacheEntry) #if DEBUG // XXX debug code to make sure we have the entry we're trying to remove - nsCacheEntry *check = GetEntry(cacheEntry->mKey); + nsCacheEntry *check = GetEntry(&(cacheEntry->mKey)); NS_ASSERTION(check == cacheEntry, "### Attempting to remove unknown cache entry!!!"); #endif - (void) PL_DHashTableOperate(&table, cacheEntry->mKey, PL_DHASH_REMOVE); + (void) PL_DHashTableOperate(&table, &(cacheEntry->mKey), PL_DHASH_REMOVE); } @@ -504,7 +498,7 @@ nsCacheEntryHashTable::MatchEntry(PLDHashTable * /* table */, NS_ASSERTION(key != nullptr, "### nsCacheEntryHashTable::MatchEntry : null key"); nsCacheEntry *cacheEntry = ((nsCacheEntryHashTableEntry *)hashEntry)->cacheEntry; - return cacheEntry->mKey->Equals(*(nsCString *)key); + return cacheEntry->mKey.Equals(*(nsCString *)key); } diff --git a/netwerk/cache/nsCacheEntry.h b/netwerk/cache/nsCacheEntry.h index 5f7d16db8b19..654491b68c3a 100644 --- a/netwerk/cache/nsCacheEntry.h +++ b/netwerk/cache/nsCacheEntry.h @@ -31,7 +31,7 @@ class nsCacheEntry : public PRCList { public: - nsCacheEntry(nsCString * key, + nsCacheEntry(const nsACString & key, bool streamBased, nsCacheStoragePolicy storagePolicy); ~nsCacheEntry(); @@ -43,7 +43,7 @@ public: nsCacheDevice * device, nsCacheEntry ** result); - nsCString * Key() { return mKey; } + nsCString * Key() { return &mKey; } PRInt32 FetchCount() { return mFetchCount; } void SetFetchCount( PRInt32 count) { mFetchCount = count; } @@ -59,7 +59,7 @@ public: void SetExpirationTime( PRUint32 expires) { mExpirationTime = expires; } PRUint32 Size() - { return mDataSize + mMetaData.Size() + (mKey ? mKey->Length() : 0); } + { return mDataSize + mMetaData.Size() + mKey.Length() ; } nsCacheDevice * CacheDevice() { return mCacheDevice; } void SetCacheDevice( nsCacheDevice * device) { mCacheDevice = device; } @@ -209,7 +209,7 @@ private: void MarkActive() { mFlags |= eActiveMask; } void MarkInactive() { mFlags &= ~eActiveMask; } - nsCString * mKey; // 4 // XXX ask scc about const'ness + nsCString mKey; PRUint32 mFetchCount; // 4 PRUint32 mLastFetched; // 4 PRUint32 mLastModified; // 4 diff --git a/netwerk/cache/nsCacheRequest.h b/netwerk/cache/nsCacheRequest.h index 462718939fc5..5cedd212868c 100644 --- a/netwerk/cache/nsCacheRequest.h +++ b/netwerk/cache/nsCacheRequest.h @@ -28,7 +28,7 @@ private: friend class nsCacheEntry; friend class nsProcessRequestEvent; - nsCacheRequest( nsCString * key, + nsCacheRequest( const nsACString & key, nsICacheListener * listener, nsCacheAccessMode accessRequested, bool blockingMode, @@ -55,7 +55,6 @@ private: ~nsCacheRequest() { MOZ_COUNT_DTOR(nsCacheRequest); - delete mKey; NS_ASSERTION(PR_CLIST_IS_EMPTY(this), "request still on a list"); if (mListener) @@ -147,7 +146,7 @@ private: /** * Data members */ - nsCString * mKey; + nsCString mKey; PRUint32 mInfo; nsICacheListener * mListener; // strong ref nsCOMPtr mThread; diff --git a/netwerk/cache/nsCacheService.cpp b/netwerk/cache/nsCacheService.cpp index 9a523629f298..56e2827e7e30 100644 --- a/netwerk/cache/nsCacheService.cpp +++ b/netwerk/cache/nsCacheService.cpp @@ -1794,20 +1794,15 @@ nsCacheService::CreateRequest(nsCacheSession * session, { NS_ASSERTION(request, "CreateRequest: request is null"); - nsCString * key = new nsCString(*session->ClientID()); - if (!key) - return NS_ERROR_OUT_OF_MEMORY; - key->Append(':'); - key->Append(clientKey); + nsCAutoString key(*session->ClientID()); + key.Append(':'); + key.Append(clientKey); - if (mMaxKeyLength < key->Length()) mMaxKeyLength = key->Length(); + if (mMaxKeyLength < key.Length()) mMaxKeyLength = key.Length(); // create request - *request = new nsCacheRequest(key, listener, accessRequested, blockingMode, session); - if (!*request) { - delete key; - return NS_ERROR_OUT_OF_MEMORY; - } + *request = new nsCacheRequest(key, listener, accessRequested, + blockingMode, session); if (!listener) return NS_OK; // we're sync, we're done. @@ -2059,13 +2054,13 @@ nsCacheService::ActivateEntry(nsCacheRequest * request, return NS_ERROR_FAILURE; // search active entries (including those not bound to device) - nsCacheEntry *entry = mActiveEntries.GetEntry(request->mKey); + nsCacheEntry *entry = mActiveEntries.GetEntry(&(request->mKey)); CACHE_LOG_DEBUG(("Active entry for request %p is %p\n", request, entry)); if (!entry) { // search cache devices for entry bool collision = false; - entry = SearchCacheDevices(request->mKey, request->StoragePolicy(), &collision); + entry = SearchCacheDevices(&(request->mKey), request->StoragePolicy(), &collision); CACHE_LOG_DEBUG(("Device search for request %p returned %p\n", request, entry)); // When there is a hashkey collision just refuse to cache it... From 1d2cfc69dde3024cac9f3fb058d868f60a2ff0e1 Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Tue, 7 Aug 2012 20:32:09 -0400 Subject: [PATCH 088/169] Backout 4e54a6eb43d2 (bug 780686) and f10e4ac36ed2 (bug 772299) due to mochitest-other permaorange on a CLOSED TREE. --- dom/apps/src/Webapps.jsm | 2 +- toolkit/content/widgets/browser.xml | 6 +----- webapprt/content/webapp.js | 4 ++-- webapprt/test/chrome/browser_window-title.js | 4 ++-- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/dom/apps/src/Webapps.jsm b/dom/apps/src/Webapps.jsm index b19dd81de18b..4ac7ff9ab3ba 100644 --- a/dom/apps/src/Webapps.jsm +++ b/dom/apps/src/Webapps.jsm @@ -274,7 +274,7 @@ let DOMApplicationRegistry = { let clone = { installOrigin: aApp.installOrigin, origin: aApp.origin, - receipts: aApp.receipts ? JSON.parse(JSON.stringify(aApp.receipts)) : null, + receipts: aApp.receipts, installTime: aApp.installTime, manifestURL: aApp.manifestURL, progress: aApp.progress || 0.0, diff --git a/toolkit/content/widgets/browser.xml b/toolkit/content/widgets/browser.xml index cbd0179aae76..66eafbc84929 100644 --- a/toolkit/content/widgets/browser.xml +++ b/toolkit/content/widgets/browser.xml @@ -447,13 +447,9 @@ - diff --git a/webapprt/content/webapp.js b/webapprt/content/webapp.js index b5a98eea0bf2..632afa997ebc 100644 --- a/webapprt/content/webapp.js +++ b/webapprt/content/webapp.js @@ -61,8 +61,8 @@ function onLoad() { // available beforehand. Services.obs.addObserver(function observeOnce(subj, topic, data) { Services.obs.removeObserver(observeOnce, "webapprt-test-did-install"); - gAppBrowser.addProgressListener(progressListener, - Ci.nsIWebProgress.NOTIFY_LOCATION); + gAppBrowser.webProgress. + addProgressListener(progressListener,Ci.nsIWebProgress.NOTIFY_LOCATION); }, "webapprt-test-did-install", false); // This observer is present for the lifetime of the runtime. diff --git a/webapprt/test/chrome/browser_window-title.js b/webapprt/test/chrome/browser_window-title.js index 2e37070fcedd..91c73bad1d67 100644 --- a/webapprt/test/chrome/browser_window-title.js +++ b/webapprt/test/chrome/browser_window-title.js @@ -36,8 +36,8 @@ function test() { } }; - appBrowser.addProgressListener(progressListener, - Ci.nsIWebProgress.NOTIFY_LOCATION); + appBrowser.webProgress. + addProgressListener(progressListener, Ci.nsIWebProgress.NOTIFY_LOCATION); function testNext() { if (!tests.length) { From 66ea0de2e24453e142e9ca18832547916a66fd5f Mon Sep 17 00:00:00 2001 From: Myk Melez Date: Tue, 7 Aug 2012 13:51:44 -0700 Subject: [PATCH 089/169] bug 780686 - DOMApplicationRegistry._cloneAppObject doesn't clone the `receipts` array; r=fabrice --- dom/apps/src/Webapps.jsm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dom/apps/src/Webapps.jsm b/dom/apps/src/Webapps.jsm index 4ac7ff9ab3ba..b19dd81de18b 100644 --- a/dom/apps/src/Webapps.jsm +++ b/dom/apps/src/Webapps.jsm @@ -274,7 +274,7 @@ let DOMApplicationRegistry = { let clone = { installOrigin: aApp.installOrigin, origin: aApp.origin, - receipts: aApp.receipts, + receipts: aApp.receipts ? JSON.parse(JSON.stringify(aApp.receipts)) : null, installTime: aApp.installTime, manifestURL: aApp.manifestURL, progress: aApp.progress || 0.0, From 5e9898d8e096d6a0608eb4a828623b195cb95cef Mon Sep 17 00:00:00 2001 From: Myk Melez Date: Tue, 7 Aug 2012 13:55:38 -0700 Subject: [PATCH 090/169] bug 772299 - widget's addProgressListener method should pass through aNotifyMask argument; r=gavin --- toolkit/content/widgets/browser.xml | 6 +++++- webapprt/content/webapp.js | 4 ++-- webapprt/test/chrome/browser_window-title.js | 4 ++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/toolkit/content/widgets/browser.xml b/toolkit/content/widgets/browser.xml index 66eafbc84929..cbd0179aae76 100644 --- a/toolkit/content/widgets/browser.xml +++ b/toolkit/content/widgets/browser.xml @@ -447,9 +447,13 @@ + diff --git a/webapprt/content/webapp.js b/webapprt/content/webapp.js index 632afa997ebc..b5a98eea0bf2 100644 --- a/webapprt/content/webapp.js +++ b/webapprt/content/webapp.js @@ -61,8 +61,8 @@ function onLoad() { // available beforehand. Services.obs.addObserver(function observeOnce(subj, topic, data) { Services.obs.removeObserver(observeOnce, "webapprt-test-did-install"); - gAppBrowser.webProgress. - addProgressListener(progressListener,Ci.nsIWebProgress.NOTIFY_LOCATION); + gAppBrowser.addProgressListener(progressListener, + Ci.nsIWebProgress.NOTIFY_LOCATION); }, "webapprt-test-did-install", false); // This observer is present for the lifetime of the runtime. diff --git a/webapprt/test/chrome/browser_window-title.js b/webapprt/test/chrome/browser_window-title.js index 91c73bad1d67..2e37070fcedd 100644 --- a/webapprt/test/chrome/browser_window-title.js +++ b/webapprt/test/chrome/browser_window-title.js @@ -36,8 +36,8 @@ function test() { } }; - appBrowser.webProgress. - addProgressListener(progressListener, Ci.nsIWebProgress.NOTIFY_LOCATION); + appBrowser.addProgressListener(progressListener, + Ci.nsIWebProgress.NOTIFY_LOCATION); function testNext() { if (!tests.length) { From f8def1114c659de64628e0bd9a1f88f8e60689c9 Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Tue, 7 Aug 2012 20:49:06 -0400 Subject: [PATCH 091/169] Bug 761077 - Build xptcall on FreeBSD ia64/ppc/ppc64/sparc64. r=bsmedberg --- xpcom/reflect/xptcall/src/md/unix/Makefile.in | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/xpcom/reflect/xptcall/src/md/unix/Makefile.in b/xpcom/reflect/xptcall/src/md/unix/Makefile.in index ae6ed6626252..2783957eef4a 100644 --- a/xpcom/reflect/xptcall/src/md/unix/Makefile.in +++ b/xpcom/reflect/xptcall/src/md/unix/Makefile.in @@ -70,7 +70,7 @@ endif endif endif # IA64 Linux -ifneq (,$(filter Linux,$(OS_ARCH))) +ifneq (,$(filter Linux FreeBSD,$(OS_ARCH))) ifneq (,$(findstring ia64,$(OS_TEST))) CPPSRCS := xptcinvoke_ipf64.cpp xptcstubs_ipf64.cpp ASFILES := xptcstubs_asm_ipf64.s xptcinvoke_asm_ipf64.s @@ -269,7 +269,7 @@ endif # # Linux/PPC # -ifeq ($(OS_ARCH)$(OS_TEST),Linuxpowerpc) +ifneq (,$(filter Linuxpowerpc FreeBSDpowerpc,$(OS_ARCH)$(OS_TEST))) CPPSRCS := xptcinvoke_ppc_linux.cpp xptcstubs_ppc_linux.cpp ASFILES := xptcinvoke_asm_ppc_linux.s xptcstubs_asm_ppc_linux.s AS := $(CC) -c -x assembler-with-cpp @@ -278,7 +278,7 @@ endif # # Linux/PPC64 # -ifeq ($(OS_ARCH)$(OS_TEST),Linuxpowerpc64) +ifneq (,$(filter Linuxpowerpc64 FreeBSDpowerpc64,$(OS_ARCH)$(OS_TEST))) CPPSRCS := xptcinvoke_ppc64_linux.cpp xptcstubs_ppc64_linux.cpp ASFILES := xptcinvoke_asm_ppc64_linux.s xptcstubs_asm_ppc64_linux.s AS := $(CC) -c -x assembler-with-cpp @@ -350,7 +350,7 @@ endif # # OpenBSD/SPARC64 # -ifeq ($(OS_ARCH)$(OS_TEST),OpenBSDsparc64) +ifneq (,$(filter OpenBSDsparc64 FreeBSDsparc64,$(OS_ARCH)$(OS_TEST))) CPPSRCS := xptcinvoke_sparc64_openbsd.cpp xptcstubs_sparc64_openbsd.cpp ASFILES := xptcinvoke_asm_sparc64_openbsd.s xptcstubs_asm_sparc64_openbsd.s endif From f31aa529d03a30f8ce617939ebc195d41bbc1a46 Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Tue, 7 Aug 2012 20:49:07 -0400 Subject: [PATCH 092/169] Bug 761077 - Use same xptcall stubs on FreeBSD/ia64 as on Linux/ia64. r=bsmedberg --- xpcom/reflect/xptcall/public/genstubs.pl | 2 +- xpcom/reflect/xptcall/public/xptcstubsdecl.inc | 2 +- xpcom/reflect/xptcall/src/xptcprivate.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/xpcom/reflect/xptcall/public/genstubs.pl b/xpcom/reflect/xptcall/public/genstubs.pl index b8a87a5e7bfe..918c4cf1af85 100644 --- a/xpcom/reflect/xptcall/public/genstubs.pl +++ b/xpcom/reflect/xptcall/public/genstubs.pl @@ -44,7 +44,7 @@ print OUTFILE "* 0 is QueryInterface\n"; print OUTFILE "* 1 is AddRef\n"; print OUTFILE "* 2 is Release\n"; print OUTFILE "*/\n"; -print OUTFILE "#if !defined(__ia64) || (!defined(__hpux) && !defined(__linux__))\n"; +print OUTFILE "#if !defined(__ia64) || (!defined(__hpux) && !defined(__linux__) && !defined(__FreeBSD__))\n"; for($i = 0; $i < $entry_count; $i++) { print OUTFILE "NS_IMETHOD Stub",$i+3,"();\n"; } diff --git a/xpcom/reflect/xptcall/public/xptcstubsdecl.inc b/xpcom/reflect/xptcall/public/xptcstubsdecl.inc index eb66761d8eee..807db26e04c1 100644 --- a/xpcom/reflect/xptcall/public/xptcstubsdecl.inc +++ b/xpcom/reflect/xptcall/public/xptcstubsdecl.inc @@ -8,7 +8,7 @@ * 1 is AddRef * 2 is Release */ -#if !defined(__ia64) || (!defined(__hpux) && !defined(__linux__)) +#if !defined(__ia64) || (!defined(__hpux) && !defined(__linux__) && !defined(__FreeBSD__)) NS_IMETHOD Stub3(); NS_IMETHOD Stub4(); NS_IMETHOD Stub5(); diff --git a/xpcom/reflect/xptcall/src/xptcprivate.h b/xpcom/reflect/xptcall/src/xptcprivate.h index d903ced34182..e4ec8326dce4 100644 --- a/xpcom/reflect/xptcall/src/xptcprivate.h +++ b/xpcom/reflect/xptcall/src/xptcprivate.h @@ -14,7 +14,7 @@ class xptiInterfaceEntry; -#if !defined(__ia64) || (!defined(__hpux) && !defined(__linux__)) +#if !defined(__ia64) || (!defined(__hpux) && !defined(__linux__) && !defined(__FreeBSD__)) #define STUB_ENTRY(n) NS_IMETHOD Stub##n() = 0; #else #define STUB_ENTRY(n) NS_IMETHOD Stub##n(PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64) = 0; @@ -31,7 +31,7 @@ public: #undef STUB_ENTRY #undef SENTINEL_ENTRY -#if !defined(__ia64) || (!defined(__hpux) && !defined(__linux__)) +#if !defined(__ia64) || (!defined(__hpux) && !defined(__linux__) && !defined(__FreeBSD__)) #define STUB_ENTRY(n) NS_IMETHOD Stub##n(); #else #define STUB_ENTRY(n) NS_IMETHOD Stub##n(PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64,PRUint64); From 0e2b7283833c05943ae6545806845c829062a1aa Mon Sep 17 00:00:00 2001 From: David Rajchenbach-Teller Date: Tue, 7 Aug 2012 20:49:07 -0400 Subject: [PATCH 093/169] Bug 780498 - More general fix. r=nfroyd --- .../components/osfile/osfile_unix_front.jsm | 87 ++++++++----------- 1 file changed, 35 insertions(+), 52 deletions(-) diff --git a/toolkit/components/osfile/osfile_unix_front.jsm b/toolkit/components/osfile/osfile_unix_front.jsm index 33feb6da2270..85e12e0206da 100644 --- a/toolkit/components/osfile/osfile_unix_front.jsm +++ b/toolkit/components/osfile/osfile_unix_front.jsm @@ -335,22 +335,6 @@ UnixFile.copyfile(sourcePath, destPath, null, flags) ); }; - - // This implementation uses |copyfile(3)|, from the BSD library. - // Adding moving of hierarchies and/or attributes is just a flag - // away. - File.move = function movefile(sourcePath, destPath, options) { - // This implementation uses |copyfile(3)|, from the BSD library. - // It can move directory hierarchies. - options = options || noOptions; - let flags = Const.COPYFILE_DATA | Const.COPYFILE_MOVE; - if (options.noOverwrite) { - flags |= Const.COPYFILE_EXCL; - } - throw_on_negative("move", - UnixFile.copyfile(sourcePath, destPath, null, flags) - ); - }; } else { // If the OS does not implement file copying for us, we need to // implement it ourselves. For this purpose, we need to define @@ -474,36 +458,37 @@ pipe_write.dispose(); } }; - } else { - // Fallback implementation of pump for other Unix platforms. - pump = pump_userland; - } - - // Implement |copy| using |pump|. - // This implementation would require some work before being able to - // copy directories - File.copy = function copy(sourcePath, destPath, options) { - options = options || noOptions; - let source, dest; - let result; - try { - source = File.open(sourcePath); - if (options.noOverwrite) { - dest = File.open(destPath, {create:true}); - } else { - dest = File.open(destPath, {write:true}); - } - result = pump(source, dest, options); - } catch (x) { - if (dest) { - dest.close(); - } - if (source) { - source.close(); - } - throw x; + } else { + // Fallback implementation of pump for other Unix platforms. + pump = pump_userland; } - }; + + // Implement |copy| using |pump|. + // This implementation would require some work before being able to + // copy directories + File.copy = function copy(sourcePath, destPath, options) { + options = options || noOptions; + let source, dest; + let result; + try { + source = File.open(sourcePath); + if (options.noOverwrite) { + dest = File.open(destPath, {create:true}); + } else { + dest = File.open(destPath, {write:true}); + } + result = pump(source, dest, options); + } catch (x) { + if (dest) { + dest.close(); + } + if (source) { + source.close(); + } + throw x; + } + }; + } // End of definition of copy // Implement |move| using |rename| (wherever possible) or |copy| // (if files are on distinct devices). @@ -539,13 +524,11 @@ throw new File.Error(); } - // Otherwise, copy and remove. - File.copy(sourcePath, destPath, options); - // FIXME: Clean-up in case of copy error? - File.remove(sourcePath); - }; - - } // End of definition of copy/move + // Otherwise, copy and remove. + File.copy(sourcePath, destPath, options); + // FIXME: Clean-up in case of copy error? + File.remove(sourcePath); + }; /** * Iterate on one directory. From 6ac61a78ee1d5c55da08ba07f501f00f3242b861 Mon Sep 17 00:00:00 2001 From: David Rajchenbach-Teller Date: Tue, 7 Aug 2012 20:49:07 -0400 Subject: [PATCH 094/169] Bug 780498 - Test that OS.File.move removes original file. r=yoric --- .../osfile/tests/mochi/worker_test_osfile_front.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/toolkit/components/osfile/tests/mochi/worker_test_osfile_front.js b/toolkit/components/osfile/tests/mochi/worker_test_osfile_front.js index ce93834b39ae..b66925a16361 100644 --- a/toolkit/components/osfile/tests/mochi/worker_test_osfile_front.js +++ b/toolkit/components/osfile/tests/mochi/worker_test_osfile_front.js @@ -192,9 +192,18 @@ function test_move_file() ok(true, "test_move_file: Move complete"); - // 3. Check + // 3. Check that destination exists compare_files("test_move_file", src_file_name, tmp2_file_name); + // 4. Check that original file does not exist anymore + let exn; + try { + OS.File.open(tmp_file_name); + } catch (x) { + exn = x; + } + ok(!!exn, "test_move_file: Original file has been removed"); + ok(true, "test_move_file: Cleaning up"); OS.File.remove(tmp2_file_name); } From d4a7f8bbdaeb9f4d3e0d74181cbaea6d215ec5c7 Mon Sep 17 00:00:00 2001 From: David Rajchenbach-Teller Date: Tue, 7 Aug 2012 20:49:07 -0400 Subject: [PATCH 095/169] Bug 780604 - Fix merge snafu in Windows version of OS.File.DirectoryIterator. r=yoric --- toolkit/components/osfile/osfile_win_back.jsm | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/toolkit/components/osfile/osfile_win_back.jsm b/toolkit/components/osfile/osfile_win_back.jsm index bfc0a70f0f98..5431470c0716 100644 --- a/toolkit/components/osfile/osfile_win_back.jsm +++ b/toolkit/components/osfile/osfile_win_back.jsm @@ -81,16 +81,7 @@ * a file descriptor in case of success. */ Types.maybe_HANDLE = - new Type("maybe_HANDLE", - Types.HANDLE.implementation, - function (maybe) { - if (ctypes.cast(maybe, ctypes.int).value == invalid_handle) { - // Ensure that API clients can effectively compare against - // Const.INVALID_HANDLE_VALUE. Without this cast, - // == would always return |false|. - return invalid_handle; - } - return ctypes.CDataFinalizer(maybe, _CloseHandle); + Types.maybe_HANDLE.withName("maybe_find_HANDLE"); }); /** From e6ca420bb5cb8bad36a6dfbec2c030ce5e7b2e34 Mon Sep 17 00:00:00 2001 From: Mike Habicher Date: Tue, 7 Aug 2012 20:49:07 -0400 Subject: [PATCH 096/169] Bug 780905 - Remove excess logging from DOMCameraManager. r=smaug --- dom/camera/DOMCameraManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dom/camera/DOMCameraManager.cpp b/dom/camera/DOMCameraManager.cpp index 3075c7ca667d..4b29c97b764d 100644 --- a/dom/camera/DOMCameraManager.cpp +++ b/dom/camera/DOMCameraManager.cpp @@ -7,7 +7,7 @@ #include "nsDOMClassInfo.h" #include "DictionaryHelpers.h" -#define DOM_CAMERA_LOG_LEVEL 3 +#define DOM_CAMERA_LOG_LEVEL DOM_CAMERA_LOG_NOTHING #include "CameraCommon.h" using namespace mozilla; From f92bb2378a994635284cfef2aa8ba0a072dc68f7 Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Fri, 27 Jul 2012 19:58:26 -0400 Subject: [PATCH 097/169] bug 780203 - add [u]intn_t types to xpidl r=khuey --- xpcom/idl-parser/typelib.py | 7 +++++++ xpcom/idl-parser/xpidl.py | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/xpcom/idl-parser/typelib.py b/xpcom/idl-parser/typelib.py index 3fd4f315618b..84fca785ee5a 100644 --- a/xpcom/idl-parser/typelib.py +++ b/xpcom/idl-parser/typelib.py @@ -18,6 +18,13 @@ TypeMap = { # builtins 'boolean': xpt.Type.Tags.boolean, 'void': xpt.Type.Tags.void, + 'int16_t': xpt.Type.Tags.int16, + 'int32_t': xpt.Type.Tags.int32, + 'int64_t': xpt.Type.Tags.int64, + 'uint8_t': xpt.Type.Tags.uint8, + 'uint16_t': xpt.Type.Tags.uint16, + 'uint32_t': xpt.Type.Tags.uint32, + 'uint64_t': xpt.Type.Tags.uint64, 'octet': xpt.Type.Tags.uint8, 'short': xpt.Type.Tags.int16, 'long': xpt.Type.Tags.int32, diff --git a/xpcom/idl-parser/xpidl.py b/xpcom/idl-parser/xpidl.py index 003bde66c529..11d5d8f02922 100644 --- a/xpcom/idl-parser/xpidl.py +++ b/xpcom/idl-parser/xpidl.py @@ -120,6 +120,13 @@ class Builtin(object): builtinNames = [ Builtin('boolean', 'bool'), Builtin('void', 'void'), + Builtin('int16_t', 'int16_t', True, True), + Builtin('int32_t', 'int32_t', True, True), + Builtin('int64_t', 'int64_t', True, False), + Builtin('uint8_t', 'uint8_t'), + Builtin('uint16_t', 'uint16_t', False, True), + Builtin('uint32_t', 'uint32_t', False, True), + Builtin('uint64_t', 'uint64_t', False, False), Builtin('octet', 'PRUint8'), Builtin('short', 'PRInt16', True, True), Builtin('long', 'PRInt32', True, True), From 23ef63f0677cbf884d5ec9ac8ce5462378d956bf Mon Sep 17 00:00:00 2001 From: Patrick McManus Date: Tue, 7 Aug 2012 21:49:53 -0400 Subject: [PATCH 098/169] bug 780104 - fail gracefully on invalid spdy dictionary r=honzab --- netwerk/protocol/http/SpdySession2.cpp | 10 +++++++++- netwerk/protocol/http/SpdySession3.cpp | 10 +++++++++- netwerk/protocol/http/SpdyStream3.cpp | 10 +++++++++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/netwerk/protocol/http/SpdySession2.cpp b/netwerk/protocol/http/SpdySession2.cpp index 9be73198f4a8..2f2b02e4a57b 100644 --- a/netwerk/protocol/http/SpdySession2.cpp +++ b/netwerk/protocol/http/SpdySession2.cpp @@ -569,6 +569,7 @@ SpdySession2::DownstreamUncompress(char *blockStart, PRUint32 blockLen) mDownstreamZlib.avail_in = blockLen; mDownstreamZlib.next_in = reinterpret_cast(blockStart); + bool triedDictionary = false; do { mDownstreamZlib.next_out = @@ -577,11 +578,18 @@ SpdySession2::DownstreamUncompress(char *blockStart, PRUint32 blockLen) mDownstreamZlib.avail_out = mDecompressBufferSize - mDecompressBufferUsed; int zlib_rv = inflate(&mDownstreamZlib, Z_NO_FLUSH); - if (zlib_rv == Z_NEED_DICT) + if (zlib_rv == Z_NEED_DICT) { + if (triedDictionary) { + LOG3(("SpdySession2::DownstreamUncompress %p Dictionary Error\n", this)); + return NS_ERROR_FAILURE; + } + + triedDictionary = true; inflateSetDictionary(&mDownstreamZlib, reinterpret_cast (SpdyStream2::kDictionary), strlen(SpdyStream2::kDictionary) + 1); + } if (zlib_rv == Z_DATA_ERROR || zlib_rv == Z_MEM_ERROR) return NS_ERROR_FAILURE; diff --git a/netwerk/protocol/http/SpdySession3.cpp b/netwerk/protocol/http/SpdySession3.cpp index 9a9fb7c03153..8687a5c56407 100644 --- a/netwerk/protocol/http/SpdySession3.cpp +++ b/netwerk/protocol/http/SpdySession3.cpp @@ -571,15 +571,23 @@ SpdySession3::UncompressAndDiscard(PRUint32 offset, unsigned char trash[2048]; mDownstreamZlib.avail_in = blockLen; mDownstreamZlib.next_in = reinterpret_cast(blockStart); + bool triedDictionary = false; do { mDownstreamZlib.next_out = trash; mDownstreamZlib.avail_out = sizeof(trash); int zlib_rv = inflate(&mDownstreamZlib, Z_NO_FLUSH); - if (zlib_rv == Z_NEED_DICT) + if (zlib_rv == Z_NEED_DICT) { + if (triedDictionary) { + LOG3(("SpdySession3::UncompressAndDiscard %p Dictionary Error\n", this)); + return NS_ERROR_FAILURE; + } + + triedDictionary = true; inflateSetDictionary(&mDownstreamZlib, SpdyStream3::kDictionary, sizeof(SpdyStream3::kDictionary)); + } if (zlib_rv == Z_DATA_ERROR || zlib_rv == Z_MEM_ERROR) return NS_ERROR_FAILURE; diff --git a/netwerk/protocol/http/SpdyStream3.cpp b/netwerk/protocol/http/SpdyStream3.cpp index b6d8820d8005..a458cb8b7e3c 100644 --- a/netwerk/protocol/http/SpdyStream3.cpp +++ b/netwerk/protocol/http/SpdyStream3.cpp @@ -871,6 +871,7 @@ SpdyStream3::Uncompress(z_stream *context, context->avail_in = blockLen; context->next_in = reinterpret_cast(blockStart); + bool triedDictionary = false; do { context->next_out = @@ -879,8 +880,15 @@ SpdyStream3::Uncompress(z_stream *context, context->avail_out = mDecompressBufferSize - mDecompressBufferUsed; int zlib_rv = inflate(context, Z_NO_FLUSH); - if (zlib_rv == Z_NEED_DICT) + if (zlib_rv == Z_NEED_DICT) { + if (triedDictionary) { + LOG3(("SpdySession3::Uncompress %p Dictionary Error\n", this)); + return NS_ERROR_FAILURE; + } + + triedDictionary = true; inflateSetDictionary(context, kDictionary, sizeof(kDictionary)); + } if (zlib_rv == Z_DATA_ERROR || zlib_rv == Z_MEM_ERROR) return NS_ERROR_FAILURE; From 6cf8da54f8334fc87041f679d8f292d0b5b0b0af Mon Sep 17 00:00:00 2001 From: Doug Sherk Date: Tue, 7 Aug 2012 18:51:00 -0700 Subject: [PATCH 099/169] Bug 775447: Properly count number of touch listeners in AsyncPanZoomController r=cjones --- dom/ipc/PBrowser.ipdl | 4 +++- dom/ipc/TabChild.cpp | 29 +++++++++++++++++++++++ dom/ipc/TabChild.h | 4 +++- dom/ipc/TabParent.cpp | 9 +++++++ dom/ipc/TabParent.h | 1 + gfx/layers/ipc/AsyncPanZoomController.cpp | 11 ++++++++- gfx/layers/ipc/AsyncPanZoomController.h | 14 +++++++++++ layout/ipc/RenderFrameParent.cpp | 8 +++++++ layout/ipc/RenderFrameParent.h | 2 ++ 9 files changed, 79 insertions(+), 3 deletions(-) diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl index d45ff2ff39b4..767ffb655746 100644 --- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -232,6 +232,8 @@ parent: nsString aName, nsString aFeatures) returns (bool windowOpened); + NotifyDOMTouchListenerAdded(); + __delete__(); child: @@ -342,4 +344,4 @@ state DYING: }; } -} \ No newline at end of file +} diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 8aee4abbf25e..78f606822c4c 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -20,6 +20,7 @@ #include "mozilla/layers/CompositorChild.h" #include "mozilla/layers/PLayersChild.h" #include "mozilla/layout/RenderFrameChild.h" +#include "mozilla/unused.h" #include "nsComponentManagerUtils.h" #include "nsComponentManagerUtils.h" #include "nsContentUtils.h" @@ -106,6 +107,24 @@ TabChild::TabChild(PRUint32 aChromeFlags, bool aIsBrowserElement, printf("creating %d!\n", NS_IsMainThread()); } +nsresult +TabChild::Observe(nsISupports *aSubject, + const char *aTopic, + const PRUnichar *aData) +{ + if (!strcmp(aTopic, "dom-touch-listener-added")) { + nsCOMPtr subject(do_QueryInterface(aSubject)); + nsCOMPtr win(do_GetInterface(mWebNav)); + nsCOMPtr topSubject; + subject->GetTop(getter_AddRefs(topSubject)); + if (win == topSubject) { + SendNotifyDOMTouchListenerAdded(); + } + } + + return NS_OK; +} + nsresult TabChild::Init() { @@ -121,6 +140,16 @@ TabChild::Init() nsCOMPtr docShellItem(do_QueryInterface(mWebNav)); docShellItem->SetItemType(nsIDocShellTreeItem::typeContentWrapper); + + nsCOMPtr observerService = + do_GetService(NS_OBSERVERSERVICE_CONTRACTID); + + if (observerService) { + observerService->AddObserver(this, + "dom-touch-listener-added", + false); + } + return NS_OK; } diff --git a/dom/ipc/TabChild.h b/dom/ipc/TabChild.h index 67b6c2ade8aa..5afc520a8af2 100644 --- a/dom/ipc/TabChild.h +++ b/dom/ipc/TabChild.h @@ -140,7 +140,8 @@ class TabChild : public PBrowserChild, public nsIWindowProvider, public nsSupportsWeakReference, public nsIDialogCreator, - public nsITabChild + public nsITabChild, + public nsIObserver { typedef mozilla::layout::RenderFrameChild RenderFrameChild; typedef mozilla::dom::ClonedMessageData ClonedMessageData; @@ -166,6 +167,7 @@ public: NS_DECL_NSIWINDOWPROVIDER NS_DECL_NSIDIALOGCREATOR NS_DECL_NSITABCHILD + NS_DECL_NSIOBSERVER virtual bool RecvLoadURL(const nsCString& uri); virtual bool RecvShow(const nsIntSize& size); diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index 39c34f12d713..5e91c8aa02e8 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -1090,5 +1090,14 @@ TabParent::RecvBrowserFrameOpenWindow(PBrowserParent* aOpener, return true; } +bool +TabParent::RecvNotifyDOMTouchListenerAdded() +{ + if (RenderFrameParent* rfp = GetRenderFrame()) { + rfp->NotifyDOMTouchListenerAdded(); + } + return true; +} + } // namespace tabs } // namespace mozilla diff --git a/dom/ipc/TabParent.h b/dom/ipc/TabParent.h index b3b80598b577..f7710abfa7e6 100644 --- a/dom/ipc/TabParent.h +++ b/dom/ipc/TabParent.h @@ -101,6 +101,7 @@ public: virtual bool RecvSetBackgroundColor(const nscolor& aValue); virtual bool RecvGetDPI(float* aValue); virtual bool RecvGetWidgetNativeData(WindowsHandle* aValue); + virtual bool RecvNotifyDOMTouchListenerAdded(); virtual PContentDialogParent* AllocPContentDialog(const PRUint32& aType, const nsCString& aName, const nsCString& aFeatures, diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index 7972f567bbff..9a4252560d04 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -53,7 +53,8 @@ AsyncPanZoomController::AsyncPanZoomController(GeckoContentController* aGeckoCon mLastSampleTime(TimeStamp::Now()), mState(NOTHING), mDPI(72), - mContentPainterStatus(CONTENT_IDLE) + mContentPainterStatus(CONTENT_IDLE), + mMayHaveTouchListeners(false) { if (aGestures == USE_GESTURE_DETECTOR) { mGestureEventListener = new GestureEventListener(this); @@ -784,6 +785,10 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aViewportFr // we get a larger displayport. This is very bad because we're wasting a // paint and not initializating the displayport correctly. RequestContentRepaint(); + + // Assuming a first paint means a new page has been loaded, clear the flag + // indicating that we may have touch listeners. + mMayHaveTouchListeners = false; } else if (!mFrameMetrics.mContentRect.IsEqualEdges(aViewportFrame.mContentRect)) { mFrameMetrics.mCSSContentRect = aViewportFrame.mCSSContentRect; SetPageRect(mFrameMetrics.mCSSContentRect); @@ -802,5 +807,9 @@ void AsyncPanZoomController::UpdateViewportSize(int aWidth, int aHeight) { mFrameMetrics = metrics; } +void AsyncPanZoomController::NotifyDOMTouchListenerAdded() { + mMayHaveTouchListeners = true; +} + } } diff --git a/gfx/layers/ipc/AsyncPanZoomController.h b/gfx/layers/ipc/AsyncPanZoomController.h index 2322b06e5037..82122c54f662 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.h +++ b/gfx/layers/ipc/AsyncPanZoomController.h @@ -99,6 +99,16 @@ public: */ void UpdateViewportSize(int aWidth, int aHeight); + /** + * A DOM touch listener has been added. When called, we enable the machinery + * that allows touch listeners to preventDefault any touch inputs. This should + * not be called unless there are actually touch listeners as it introduces + * potentially unbounded lag because it causes a round-trip through content. + * Usually, if content is responding in a timely fashion, this only introduces + * a nearly constant few hundred ms of lag. + */ + void NotifyDOMTouchListenerAdded(); + // -------------------------------------------------------------------------- // These methods must only be called on the compositor thread. // @@ -394,6 +404,10 @@ private: // requests a repaint. ContentPainterStatus mContentPainterStatus; + // Whether or not we might have touch listeners. This is a conservative + // approximation and may not be accurate. + bool mMayHaveTouchListeners; + friend class Axis; }; diff --git a/layout/ipc/RenderFrameParent.cpp b/layout/ipc/RenderFrameParent.cpp index 896b11d9aac3..43ae7717228d 100644 --- a/layout/ipc/RenderFrameParent.cpp +++ b/layout/ipc/RenderFrameParent.cpp @@ -852,6 +852,14 @@ RenderFrameParent::BuildDisplayList(nsDisplayListBuilder* aBuilder, bounds)); } +void +RenderFrameParent::NotifyDOMTouchListenerAdded() +{ + if (mPanZoomController) { + mPanZoomController->NotifyDOMTouchListenerAdded(); + } +} + } // namespace layout } // namespace mozilla diff --git a/layout/ipc/RenderFrameParent.h b/layout/ipc/RenderFrameParent.h index a7ea91feb97a..aa30f7b59561 100644 --- a/layout/ipc/RenderFrameParent.h +++ b/layout/ipc/RenderFrameParent.h @@ -93,6 +93,8 @@ public: void NotifyDimensionsChanged(int width, int height); + void NotifyDOMTouchListenerAdded(); + protected: void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE; From a52dd8cc39c7584f15364f944961b93ae6a014ce Mon Sep 17 00:00:00 2001 From: Doug Sherk Date: Tue, 7 Aug 2012 18:51:02 -0700 Subject: [PATCH 100/169] Bug 775448: Disable async scrolling when we detect a scrollable subframe r=cjones --- dom/browser-element/BrowserElementScrolling.js | 10 ++++++++++ dom/ipc/TabChild.cpp | 9 +++++++++ gfx/layers/ipc/AsyncPanZoomController.cpp | 16 +++++++++++++++- gfx/layers/ipc/AsyncPanZoomController.h | 14 ++++++++++++++ layout/ipc/PRenderFrame.ipdl | 2 ++ layout/ipc/RenderFrameChild.cpp | 6 ++++++ layout/ipc/RenderFrameChild.h | 2 ++ layout/ipc/RenderFrameParent.cpp | 9 +++++++++ layout/ipc/RenderFrameParent.h | 2 ++ 9 files changed, 69 insertions(+), 1 deletion(-) diff --git a/dom/browser-element/BrowserElementScrolling.js b/dom/browser-element/BrowserElementScrolling.js index c17f27daddaa..dc5a90ae04e4 100644 --- a/dom/browser-element/BrowserElementScrolling.js +++ b/dom/browser-element/BrowserElementScrolling.js @@ -43,6 +43,16 @@ const ContentPanning = { let oldTarget = this.target; [this.target, this.scrollCallback] = this.getPannable(evt.target); + // If we found a target, that means we have found a scrollable subframe. In + // this case, and if we are using async panning and zooming on the parent + // frame, inform the pan/zoom controller that it should not attempt to + // handle any touch events it gets until the next batch (meaning the next + // time we get a touch end). + if (this.target != null && ContentPanning._asyncPanZoomForViewportFrame) { + var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); + os.notifyObservers(docShell, 'cancel-default-pan-zoom', null); + } + // If there is a pan animation running (from a previous pan gesture) and // the user touch back the screen, stop this animation immediatly and // prevent the possible click action if the touch happens on the same diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 78f606822c4c..c20b8cc96aa7 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -120,6 +120,12 @@ TabChild::Observe(nsISupports *aSubject, if (win == topSubject) { SendNotifyDOMTouchListenerAdded(); } + } else if (!strcmp(aTopic, "cancel-default-pan-zoom")) { + nsCOMPtr docShell(do_QueryInterface(aSubject)); + nsCOMPtr tabChild(GetTabChildFrom(docShell)); + if (tabChild == this) { + mRemoteFrame->CancelDefaultPanZoom(); + } } return NS_OK; @@ -148,6 +154,9 @@ TabChild::Init() observerService->AddObserver(this, "dom-touch-listener-added", false); + observerService->AddObserver(this, + "cancel-default-pan-zoom", + false); } return NS_OK; diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index 9a4252560d04..91a998e7743e 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -54,7 +54,8 @@ AsyncPanZoomController::AsyncPanZoomController(GeckoContentController* aGeckoCon mState(NOTHING), mDPI(72), mContentPainterStatus(CONTENT_IDLE), - mMayHaveTouchListeners(false) + mMayHaveTouchListeners(false), + mDisableNextTouchBatch(false) { if (aGestures == USE_GESTURE_DETECTOR) { mGestureEventListener = new GestureEventListener(this); @@ -223,6 +224,10 @@ nsEventStatus AsyncPanZoomController::OnTouchStart(const MultiTouchInput& aEvent } nsEventStatus AsyncPanZoomController::OnTouchMove(const MultiTouchInput& aEvent) { + if (mDisableNextTouchBatch) { + return nsEventStatus_eIgnore; + } + switch (mState) { case FLING: case NOTHING: @@ -254,6 +259,11 @@ nsEventStatus AsyncPanZoomController::OnTouchMove(const MultiTouchInput& aEvent) } nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent) { + if (mDisableNextTouchBatch) { + mDisableNextTouchBatch = false; + return nsEventStatus_eIgnore; + } + switch (mState) { case FLING: // Should never happen. @@ -811,5 +821,9 @@ void AsyncPanZoomController::NotifyDOMTouchListenerAdded() { mMayHaveTouchListeners = true; } +void AsyncPanZoomController::CancelDefaultPanZoom() { + mDisableNextTouchBatch = true; +} + } } diff --git a/gfx/layers/ipc/AsyncPanZoomController.h b/gfx/layers/ipc/AsyncPanZoomController.h index 82122c54f662..17956ad090e9 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.h +++ b/gfx/layers/ipc/AsyncPanZoomController.h @@ -109,6 +109,16 @@ public: */ void NotifyDOMTouchListenerAdded(); + /** + * We have found a scrollable subframe, so disable our machinery until we hit + * a touch end or a new touch start. This prevents us from accidentally + * panning both the subframe and the parent frame. + * + * XXX/bug 775452: We should eventually be supporting async scrollable + * subframes. + */ + void CancelDefaultPanZoom(); + // -------------------------------------------------------------------------- // These methods must only be called on the compositor thread. // @@ -408,6 +418,10 @@ private: // approximation and may not be accurate. bool mMayHaveTouchListeners; + // Flag used to determine whether or not we should disable handling of the + // next batch of touch events. This is used for sync scrolling of subframes. + bool mDisableNextTouchBatch; + friend class Axis; }; diff --git a/layout/ipc/PRenderFrame.ipdl b/layout/ipc/PRenderFrame.ipdl index d84180699647..0a30fc838748 100644 --- a/layout/ipc/PRenderFrame.ipdl +++ b/layout/ipc/PRenderFrame.ipdl @@ -41,6 +41,8 @@ parent: async NotifyCompositorTransaction(); + async CancelDefaultPanZoom(); + async __delete__(); state EMPTY_OR_DIRECT_COMPOSITOR: diff --git a/layout/ipc/RenderFrameChild.cpp b/layout/ipc/RenderFrameChild.cpp index 9c3c6fe3fe22..a2af75b60272 100644 --- a/layout/ipc/RenderFrameChild.cpp +++ b/layout/ipc/RenderFrameChild.cpp @@ -32,6 +32,12 @@ RenderFrameChild::Destroy() // WARNING: |this| is dead, hands off } +void +RenderFrameChild::CancelDefaultPanZoom() +{ + SendCancelDefaultPanZoom(); +} + PLayersChild* RenderFrameChild::AllocPLayers() { diff --git a/layout/ipc/RenderFrameChild.h b/layout/ipc/RenderFrameChild.h index c9d6fc599604..44f38b175fa5 100644 --- a/layout/ipc/RenderFrameChild.h +++ b/layout/ipc/RenderFrameChild.h @@ -19,6 +19,8 @@ public: RenderFrameChild() {} virtual ~RenderFrameChild() {} + void CancelDefaultPanZoom(); + void Destroy(); protected: diff --git a/layout/ipc/RenderFrameParent.cpp b/layout/ipc/RenderFrameParent.cpp index 43ae7717228d..33ed541a0072 100644 --- a/layout/ipc/RenderFrameParent.cpp +++ b/layout/ipc/RenderFrameParent.cpp @@ -720,6 +720,15 @@ RenderFrameParent::RecvNotifyCompositorTransaction() return true; } +bool +RenderFrameParent::RecvCancelDefaultPanZoom() +{ + if (mPanZoomController) { + mPanZoomController->CancelDefaultPanZoom(); + } + return true; +} + PLayersParent* RenderFrameParent::AllocPLayers() { diff --git a/layout/ipc/RenderFrameParent.h b/layout/ipc/RenderFrameParent.h index aa30f7b59561..57d5587f6520 100644 --- a/layout/ipc/RenderFrameParent.h +++ b/layout/ipc/RenderFrameParent.h @@ -100,6 +100,8 @@ protected: virtual bool RecvNotifyCompositorTransaction() MOZ_OVERRIDE; + virtual bool RecvCancelDefaultPanZoom() MOZ_OVERRIDE; + virtual PLayersParent* AllocPLayers() MOZ_OVERRIDE; virtual bool DeallocPLayers(PLayersParent* aLayers) MOZ_OVERRIDE; From c69a910104c4ac9f37ac733e55a5bf48ccc9d922 Mon Sep 17 00:00:00 2001 From: Doug Sherk Date: Tue, 7 Aug 2012 18:51:03 -0700 Subject: [PATCH 101/169] Bug 775448: Add gesture cancelling support during sync subframe scrolling r=cjones --- gfx/layers/ipc/AsyncPanZoomController.cpp | 5 ++++- gfx/layers/ipc/GestureEventListener.cpp | 5 +++++ gfx/layers/ipc/GestureEventListener.h | 7 +++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index 91a998e7743e..dae6a0dbc1b5 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -148,7 +148,7 @@ AsyncPanZoomController::HandleInputEvent(const nsInputEvent& aEvent, nsEventStatus AsyncPanZoomController::HandleInputEvent(const InputData& aEvent) { nsEventStatus rv = nsEventStatus_eIgnore; - if (mGestureEventListener) { + if (mGestureEventListener && !mDisableNextTouchBatch) { nsEventStatus rv = mGestureEventListener->HandleInputEvent(aEvent); if (rv == nsEventStatus_eConsumeNoDefault) return rv; @@ -823,6 +823,9 @@ void AsyncPanZoomController::NotifyDOMTouchListenerAdded() { void AsyncPanZoomController::CancelDefaultPanZoom() { mDisableNextTouchBatch = true; + if (mGestureEventListener) { + mGestureEventListener->CancelGesture(); + } } } diff --git a/gfx/layers/ipc/GestureEventListener.cpp b/gfx/layers/ipc/GestureEventListener.cpp index e5f1f40ce261..e3a338934222 100644 --- a/gfx/layers/ipc/GestureEventListener.cpp +++ b/gfx/layers/ipc/GestureEventListener.cpp @@ -260,5 +260,10 @@ AsyncPanZoomController* GestureEventListener::GetAsyncPanZoomController() { return mAsyncPanZoomController; } +void GestureEventListener::CancelGesture() { + mTouches.Clear(); + mState = GESTURE_NONE; +} + } } diff --git a/gfx/layers/ipc/GestureEventListener.h b/gfx/layers/ipc/GestureEventListener.h index 4a227a4f2768..e715e2020760 100644 --- a/gfx/layers/ipc/GestureEventListener.h +++ b/gfx/layers/ipc/GestureEventListener.h @@ -47,6 +47,13 @@ public: */ nsEventStatus HandleInputEvent(const InputData& aEvent); + /** + * Cancels any currently active gesture. May not properly handle situations + * that require extra work at the gesture's end, like a pinch which only + * requests a repaint once it has ended. + */ + void CancelGesture(); + /** * Returns the AsyncPanZoomController stored on this class and used for * callbacks. From cb188fd4949d25f38626919aaee4fe64deafa26c Mon Sep 17 00:00:00 2001 From: Doug Sherk Date: Tue, 7 Aug 2012 18:51:05 -0700 Subject: [PATCH 102/169] Bug 780210: Fix B2G focus point calculation for pinching r=kats --- gfx/layers/ipc/AsyncPanZoomController.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index dae6a0dbc1b5..cf8a13ce30c7 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -584,7 +584,8 @@ void AsyncPanZoomController::ScaleWithFocus(float aScale, const nsIntPoint& aFoc FrameMetrics metrics(mFrameMetrics); // Don't set the scale to the inputted value, but rather multiply it in. - float scaleFactor = aScale / metrics.mResolution.width; + float scaleFactor = aScale / metrics.mResolution.width, + oldScale = metrics.mResolution.width; metrics.mResolution.width = metrics.mResolution.height = aScale; @@ -594,8 +595,8 @@ void AsyncPanZoomController::ScaleWithFocus(float aScale, const nsIntPoint& aFoc nsIntPoint scrollOffset = metrics.mViewportScrollOffset; - scrollOffset.x += aFocus.x * (scaleFactor - 1.0f); - scrollOffset.y += aFocus.y * (scaleFactor - 1.0f); + scrollOffset.x += NS_lround(float(aFocus.x) * (scaleFactor - 1.0f) / oldScale); + scrollOffset.y += NS_lround(float(aFocus.y) * (scaleFactor - 1.0f) / oldScale); metrics.mViewportScrollOffset = scrollOffset; From 7f10d611e6d8242a23716940dc52f18f6931e7e7 Mon Sep 17 00:00:00 2001 From: Doug Sherk Date: Tue, 7 Aug 2012 18:51:08 -0700 Subject: [PATCH 103/169] Bug 775463: Implement double-tap-to-zoom content r=cjones --- .../BrowserElementScrolling.js | 182 +++++++++++++++++- dom/ipc/PBrowser.ipdl | 23 ++- dom/ipc/TabChild.cpp | 104 +++++++--- dom/ipc/TabChild.h | 15 +- dom/ipc/TabParent.cpp | 19 +- dom/ipc/TabParent.h | 2 + gfx/layers/ipc/AsyncPanZoomController.cpp | 178 +++++++++++++++-- gfx/layers/ipc/AsyncPanZoomController.h | 24 +++ gfx/layers/ipc/GeckoContentController.h | 8 + ipc/glue/IPCMessageUtils.h | 24 +++ layout/ipc/RenderFrameParent.cpp | 25 +++ layout/ipc/RenderFrameParent.h | 2 + 12 files changed, 544 insertions(+), 62 deletions(-) diff --git a/dom/browser-element/BrowserElementScrolling.js b/dom/browser-element/BrowserElementScrolling.js index dc5a90ae04e4..03b815d9379c 100644 --- a/dom/browser-element/BrowserElementScrolling.js +++ b/dom/browser-element/BrowserElementScrolling.js @@ -9,6 +9,7 @@ const ContentPanning = { }); addMessageListener("Viewport:Change", this._recvViewportChange.bind(this)); + addMessageListener("Gesture:DoubleTap", this._recvDoubleTap.bind(this)); }, handleEvent: function cp_handleEvent(evt) { @@ -196,21 +197,34 @@ const ContentPanning = { }, _recvViewportChange: function(data) { - let viewport = data.json; - let displayPort = viewport.displayPort; + let metrics = data.json; + let displayPort = metrics.displayPort; - let screenWidth = viewport.screenSize.width; - let screenHeight = viewport.screenSize.height; + let screenWidth = metrics.screenSize.width; + let screenHeight = metrics.screenSize.height; - let x = viewport.x; - let y = viewport.y; + let x = metrics.x; + let y = metrics.y; + + this._zoom = metrics.zoom; + this._viewport = new Rect(x, y, + screenWidth / metrics.zoom, + screenHeight / metrics.zoom); + this._cssPageRect = new Rect(metrics.cssPageRect.x, + metrics.cssPageRect.y, + metrics.cssPageRect.width, + metrics.cssPageRect.height); let cwu = content.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils); - cwu.setCSSViewport(screenWidth, screenHeight); + if (this._screenWidth != screenWidth || this._screenHeight != screenHeight) { + cwu.setCSSViewport(screenWidth, screenHeight); + this._screenWidth = screenWidth; + this._screenHeight = screenHeight; + } // Set scroll position cwu.setScrollPositionClampingScrollPortSize( - screenWidth / viewport.zoom, screenHeight / viewport.zoom); + screenWidth / metrics.zoom, screenHeight / metrics.zoom); content.scrollTo(x, y); cwu.setResolution(displayPort.resolution, displayPort.resolution); @@ -222,6 +236,109 @@ const ContentPanning = { displayPort.height, element); } + }, + + _recvDoubleTap: function(data) { + let data = data.json; + + // We haven't received a metrics update yet; don't do anything. + if (this._viewport == null) { + return; + } + + let win = content; + + let zoom = this._zoom; + let element = ElementTouchHelper.anyElementFromPoint(win, data.x, data.y); + if (!element) { + this._zoomOut(); + return; + } + + while (element && !this._shouldZoomToElement(element)) + element = element.parentNode; + + if (!element) { + this._zoomOut(); + } else { + const margin = 15; + let rect = ElementTouchHelper.getBoundingContentRect(element); + + let cssPageRect = this._cssPageRect; + let viewport = this._viewport; + let bRect = new Rect(Math.max(cssPageRect.left, rect.x - margin), + rect.y, + rect.w + 2 * margin, + rect.h); + // constrict the rect to the screen's right edge + bRect.width = Math.min(bRect.width, cssPageRect.right - bRect.x); + + // if the rect is already taking up most of the visible area and is stretching the + // width of the page, then we want to zoom out instead. + if (this._isRectZoomedIn(bRect, viewport)) { + this._zoomOut(); + return; + } + + rect.x = Math.round(bRect.x); + rect.y = Math.round(bRect.y); + rect.w = Math.round(bRect.width); + rect.h = Math.round(Math.min(bRect.width * viewport.height / viewport.height, bRect.height)); + + // if the block we're zooming to is really tall, and the user double-tapped + // more than a screenful of height from the top of it, then adjust the y-coordinate + // so that we center the actual point the user double-tapped upon. this prevents + // flying to the top of a page when double-tapping to zoom in (bug 761721). + // the 1.2 multiplier is just a little fuzz to compensate for bRect including horizontal + // margins but not vertical ones. + let cssTapY = viewport.y + data.y; + if ((bRect.height > rect.h) && (cssTapY > rect.y + (rect.h * 1.2))) { + rect.y = cssTapY - (rect.h / 2); + } + + var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); + os.notifyObservers(docShell, 'browser-zoom-to-rect', JSON.stringify(rect)); + } + }, + + _shouldZoomToElement: function(aElement) { + let win = aElement.ownerDocument.defaultView; + if (win.getComputedStyle(aElement, null).display == "inline") + return false; + if (aElement instanceof Ci.nsIDOMHTMLLIElement) + return false; + if (aElement instanceof Ci.nsIDOMHTMLQuoteElement) + return false; + return true; + }, + + _zoomOut: function() { + let rect = new Rect(0, 0, 0, 0); + var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); + os.notifyObservers(docShell, 'browser-zoom-to-rect', JSON.stringify(rect)); + }, + + _isRectZoomedIn: function(aRect, aViewport) { + // This function checks to see if the area of the rect visible in the + // viewport (i.e. the "overlapArea" variable below) is approximately + // the max area of the rect we can show. It also checks that the rect + // is actually on-screen by testing the left and right edges of the rect. + // In effect, this tells us whether or not zooming in to this rect + // will significantly change what the user is seeing. + const minDifference = -20; + const maxDifference = 20; + + let vRect = new Rect(aViewport.x, aViewport.y, aViewport.width, aViewport.height); + let overlap = vRect.intersect(aRect); + let overlapArea = overlap.width * overlap.height; + let availHeight = Math.min(aRect.width * vRect.height / vRect.width, aRect.height); + let showing = overlapArea / (aRect.width * availHeight); + let dw = (aRect.width - vRect.width); + let dx = (aRect.x - vRect.x); + + return (showing > 0.9 && + dx > minDifference && dx < maxDifference && + dw > minDifference && dw < maxDifference); } }; @@ -395,3 +512,52 @@ const KineticPanning = { content.mozRequestAnimationFrame(callback); } }; + +const ElementTouchHelper = { + anyElementFromPoint: function(aWindow, aX, aY) { + let cwu = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils); + let elem = cwu.elementFromPoint(aX, aY, true, true); + + let HTMLIFrameElement = Ci.nsIDOMHTMLIFrameElement; + let HTMLFrameElement = Ci.nsIDOMHTMLFrameElement; + while (elem && (elem instanceof HTMLIFrameElement || elem instanceof HTMLFrameElement)) { + let rect = elem.getBoundingClientRect(); + aX -= rect.left; + aY -= rect.top; + cwu = elem.contentDocument.defaultView.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils); + elem = cwu.elementFromPoint(aX, aY, true, true); + } + + return elem; + }, + + getBoundingContentRect: function(aElement) { + if (!aElement) + return {x: 0, y: 0, w: 0, h: 0}; + + let document = aElement.ownerDocument; + while (document.defaultView.frameElement) + document = document.defaultView.frameElement.ownerDocument; + + let cwu = document.defaultView.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils); + let scrollX = {}, scrollY = {}; + cwu.getScrollXY(false, scrollX, scrollY); + + let r = aElement.getBoundingClientRect(); + + // step out of iframes and frames, offsetting scroll values + for (let frame = aElement.ownerDocument.defaultView; frame.frameElement && frame != content; frame = frame.parent) { + // adjust client coordinates' origin to be top left of iframe viewport + let rect = frame.frameElement.getBoundingClientRect(); + let left = frame.getComputedStyle(frame.frameElement, "").borderLeftWidth; + let top = frame.getComputedStyle(frame.frameElement, "").borderTopWidth; + scrollX.value += rect.left + parseInt(left); + scrollY.value += rect.top + parseInt(top); + } + + return {x: r.left + scrollX.value, + y: r.top + scrollY.value, + w: r.width, + h: r.height }; + } +}; diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl index 767ffb655746..ae5be9649083 100644 --- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -15,6 +15,9 @@ include protocol POfflineCacheUpdate; include protocol PIndexedDB; include "gfxMatrix.h"; +include "gfxRect.h"; +include "gfxipc/ShadowLayerUtils.h"; +include "FrameMetrics.h"; include "IPC/nsGUIEventIPC.h"; include "mozilla/dom/TabMessageUtils.h"; include "mozilla/layout/RenderFrameUtils.h"; @@ -24,7 +27,9 @@ include DOMTypes; using IPC::URI; using gfxMatrix; +using gfxRect; using gfxSize; +using mozilla::layers::FrameMetrics; using mozilla::layers::LayersBackend; using mozilla::layout::ScrollingBehavior; using mozilla::WindowsHandle; @@ -234,6 +239,12 @@ parent: NotifyDOMTouchListenerAdded(); + /** + * Instructs the TabParent to forward a request to zoom to a rect given in + * CSS pixels. This rect is relative to the document. + */ + ZoomToRect(gfxRect aRect); + __delete__(); child: @@ -252,10 +263,14 @@ child: UpdateDimensions(nsRect rect, nsIntSize size); - UpdateFrame(nsIntRect displayPort, - nsIntPoint scrollOffset, - gfxSize resolution, - nsIntRect screenSize); + UpdateFrame(FrameMetrics frame); + + /** + * Requests handling of a double tap. |point| is in CSS pixels, relative to + * the scroll offset. This message is expected to round-trip back to + * ZoomToRect() with a rect indicating where we should zoom to. + */ + HandleDoubleTap(nsIntPoint point); /** * Sending an activate message moves focus to the child. diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index c20b8cc96aa7..e0b9a8ba0846 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -126,6 +126,17 @@ TabChild::Observe(nsISupports *aSubject, if (tabChild == this) { mRemoteFrame->CancelDefaultPanZoom(); } + } else if (!strcmp(aTopic, "browser-zoom-to-rect")) { + nsCOMPtr docShell(do_QueryInterface(aSubject)); + nsCOMPtr tabChild(GetTabChildFrom(docShell)); + if (tabChild == this) { + gfxRect rect; + int numAssigned = sscanf(NS_ConvertUTF16toUTF8(aData).get(), + "{\"x\":%lf,\"y\":%lf,\"w\":%lf,\"h\":%lf}", + &rect.x, &rect.y, &rect.width, &rect.height); + MOZ_ASSERT(numAssigned == 4, "Invalid JSON format"); + SendZoomToRect(rect); + } } return NS_OK; @@ -157,6 +168,9 @@ TabChild::Init() observerService->AddObserver(this, "cancel-default-pan-zoom", false); + observerService->AddObserver(this, + "browser-zoom-to-rect", + false); } return NS_OK; @@ -682,41 +696,17 @@ TabChild::RecvUpdateDimensions(const nsRect& rect, const nsIntSize& size) return true; } -bool -TabChild::RecvUpdateFrame(const nsIntRect& aDisplayPort, - const nsIntPoint& aScrollOffset, - const gfxSize& aResolution, - const nsIntRect& aScreenSize) +void +TabChild::DispatchMessageManagerMessage(const nsAString& aMessageName, + const nsACString& aJSONData) { - if (!mCx || !mTabChildGlobal) { - return true; - } - nsCString data; - data += nsPrintfCString("{ \"x\" : %d", aScrollOffset.x); - data += nsPrintfCString(", \"y\" : %d", aScrollOffset.y); - // We don't treat the x and y scales any differently for this - // semi-platform-specific code. - data += nsPrintfCString(", \"zoom\" : %f", aResolution.width); - data += nsPrintfCString(", \"displayPort\" : "); - data += nsPrintfCString("{ \"left\" : %d", aDisplayPort.X()); - data += nsPrintfCString(", \"top\" : %d", aDisplayPort.Y()); - data += nsPrintfCString(", \"width\" : %d", aDisplayPort.Width()); - data += nsPrintfCString(", \"height\" : %d", aDisplayPort.Height()); - data += nsPrintfCString(", \"resolution\" : %f", aResolution.width); - data += nsPrintfCString(" }"); - data += nsPrintfCString(", \"screenSize\" : "); - data += nsPrintfCString("{ \"width\" : %d", aScreenSize.width); - data += nsPrintfCString(", \"height\" : %d", aScreenSize.height); - data += nsPrintfCString(" }"); - data += nsPrintfCString(" }"); - JSAutoRequest ar(mCx); jsval json = JSVAL_NULL; StructuredCloneData cloneData; JSAutoStructuredCloneBuffer buffer; if (JS_ParseJSON(mCx, - static_cast(NS_ConvertUTF8toUTF16(data).get()), - data.Length(), + static_cast(NS_ConvertUTF8toUTF16(aJSONData).get()), + aJSONData.Length(), &json)) { WriteStructuredClone(mCx, json, buffer, cloneData.mClosure); cloneData.mData = buffer.data(); @@ -729,8 +719,60 @@ TabChild::RecvUpdateFrame(const nsIntRect& aDisplayPort, nsRefPtr mm = static_cast(mTabChildGlobal->mMessageManager.get()); mm->ReceiveMessage(static_cast(mTabChildGlobal), - NS_LITERAL_STRING("Viewport:Change"), false, - &cloneData, nullptr, nullptr); + aMessageName, false, &cloneData, nullptr, nullptr); +} + +bool +TabChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics) +{ + if (!mCx || !mTabChildGlobal) { + return true; + } + + nsCString data; + data += nsPrintfCString("{ \"x\" : %d", aFrameMetrics.mViewportScrollOffset.x); + data += nsPrintfCString(", \"y\" : %d", aFrameMetrics.mViewportScrollOffset.y); + // We don't treat the x and y scales any differently for this + // semi-platform-specific code. + data += nsPrintfCString(", \"zoom\" : %f", aFrameMetrics.mResolution.width); + data += nsPrintfCString(", \"displayPort\" : "); + data += nsPrintfCString("{ \"left\" : %d", aFrameMetrics.mDisplayPort.X()); + data += nsPrintfCString(", \"top\" : %d", aFrameMetrics.mDisplayPort.Y()); + data += nsPrintfCString(", \"width\" : %d", aFrameMetrics.mDisplayPort.Width()); + data += nsPrintfCString(", \"height\" : %d", aFrameMetrics.mDisplayPort.Height()); + data += nsPrintfCString(", \"resolution\" : %f", aFrameMetrics.mResolution.width); + data += nsPrintfCString(" }"); + data += nsPrintfCString(", \"screenSize\" : "); + data += nsPrintfCString("{ \"width\" : %d", aFrameMetrics.mViewport.width); + data += nsPrintfCString(", \"height\" : %d", aFrameMetrics.mViewport.height); + data += nsPrintfCString(" }"); + data += nsPrintfCString(", \"cssPageRect\" : "); + data += nsPrintfCString("{ \"x\" : %f", aFrameMetrics.mCSSContentRect.x); + data += nsPrintfCString(", \"y\" : %f", aFrameMetrics.mCSSContentRect.y); + data += nsPrintfCString(", \"width\" : %f", aFrameMetrics.mCSSContentRect.width); + data += nsPrintfCString(", \"height\" : %f", aFrameMetrics.mCSSContentRect.height); + data += nsPrintfCString(" }"); + data += nsPrintfCString(" }"); + + DispatchMessageManagerMessage(NS_LITERAL_STRING("Viewport:Change"), data); + + return true; +} + +bool +TabChild::RecvHandleDoubleTap(const nsIntPoint& aPoint) +{ + if (!mCx || !mTabChildGlobal) { + return true; + } + + nsCString data; + data += nsPrintfCString("{ \"x\" : %d", aPoint.x); + data += nsPrintfCString(", \"y\" : %d", aPoint.y); + data += nsPrintfCString(" }"); + + DispatchMessageManagerMessage(NS_LITERAL_STRING("Gesture:DoubleTap"), data); + return true; } diff --git a/dom/ipc/TabChild.h b/dom/ipc/TabChild.h index 5afc520a8af2..34c540d1fb80 100644 --- a/dom/ipc/TabChild.h +++ b/dom/ipc/TabChild.h @@ -47,6 +47,7 @@ #include "nsWeakReference.h" #include "nsITabChild.h" #include "mozilla/Attributes.h" +#include "FrameMetrics.h" struct gfxMatrix; @@ -172,10 +173,8 @@ public: virtual bool RecvLoadURL(const nsCString& uri); virtual bool RecvShow(const nsIntSize& size); virtual bool RecvUpdateDimensions(const nsRect& rect, const nsIntSize& size); - virtual bool RecvUpdateFrame(const nsIntRect& aDisplayPort, - const nsIntPoint& aScrollOffset, - const gfxSize& aResolution, - const nsIntRect& aScreenSize); + virtual bool RecvUpdateFrame(const mozilla::layers::FrameMetrics& aFrameMetrics); + virtual bool RecvHandleDoubleTap(const nsIntPoint& aPoint); virtual bool RecvActivate(); virtual bool RecvDeactivate(); virtual bool RecvMouseEvent(const nsString& aType, @@ -289,6 +288,14 @@ private: // Call RecvShow(nsIntSize(0, 0)) and block future calls to RecvShow(). void DoFakeShow(); + // Wraps up a JSON object as a structured clone and sends it to the browser + // chrome script. + // + // XXX/bug 780335: Do the work the browser chrome script does in C++ instead + // so we don't need things like this. + void DispatchMessageManagerMessage(const nsAString& aMessageName, + const nsACString& aJSONData); + nsresult BrowserFrameProvideWindow(nsIDOMWindow* aOpener, nsIURI* aURI, diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index 5e91c8aa02e8..7ff2a4701ef2 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -225,10 +225,12 @@ TabParent::UpdateDimensions(const nsRect& rect, const nsIntSize& size) void TabParent::UpdateFrame(const FrameMetrics& aFrameMetrics) { - unused << SendUpdateFrame(aFrameMetrics.mDisplayPort, - aFrameMetrics.mViewportScrollOffset, - aFrameMetrics.mResolution, - aFrameMetrics.mViewport); + unused << SendUpdateFrame(aFrameMetrics); +} + +void TabParent::HandleDoubleTap(const nsIntPoint& aPoint) +{ + unused << SendHandleDoubleTap(aPoint); } void @@ -1099,5 +1101,14 @@ TabParent::RecvNotifyDOMTouchListenerAdded() return true; } +bool +TabParent::RecvZoomToRect(const gfxRect& aRect) +{ + if (RenderFrameParent* rfp = GetRenderFrame()) { + rfp->ZoomToRect(aRect); + } + return true; +} + } // namespace tabs } // namespace mozilla diff --git a/dom/ipc/TabParent.h b/dom/ipc/TabParent.h index f7710abfa7e6..a29307b46db8 100644 --- a/dom/ipc/TabParent.h +++ b/dom/ipc/TabParent.h @@ -102,6 +102,7 @@ public: virtual bool RecvGetDPI(float* aValue); virtual bool RecvGetWidgetNativeData(WindowsHandle* aValue); virtual bool RecvNotifyDOMTouchListenerAdded(); + virtual bool RecvZoomToRect(const gfxRect& aRect); virtual PContentDialogParent* AllocPContentDialog(const PRUint32& aType, const nsCString& aName, const nsCString& aFeatures, @@ -121,6 +122,7 @@ public: void Show(const nsIntSize& size); void UpdateDimensions(const nsRect& rect, const nsIntSize& size); void UpdateFrame(const layers::FrameMetrics& aFrameMetrics); + void HandleDoubleTap(const nsIntPoint& aPoint); void Activate(); void Deactivate(); diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index cf8a13ce30c7..6d5c3fd40215 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -6,15 +6,20 @@ #include "CompositorParent.h" #include "mozilla/gfx/2D.h" +#include "mozilla/ClearOnShutdown.h" #include "mozilla/Constants.h" #include "mozilla/Util.h" #include "mozilla/XPCOM.h" #include "mozilla/Monitor.h" +#include "mozilla/StaticPtr.h" #include "AsyncPanZoomController.h" #include "GestureEventListener.h" #include "nsIThreadManager.h" #include "nsThreadUtils.h" #include "Layers.h" +#include "AnimationCommon.h" + +using namespace mozilla::css; namespace mozilla { namespace layers { @@ -44,6 +49,26 @@ static const float MIN_SKATE_SPEED = 0.5f; */ static const float AXIS_LOCK_ANGLE = M_PI / 6.0; +/** + * Duration of a zoom to animation. + */ +static const TimeDuration ZOOM_TO_DURATION = TimeDuration::FromSeconds(0.25); + +/** + * Computed time function used for sampling frames of a zoom to animation. + */ +StaticAutoPtr gComputedTimingFunction; + +/** + * Maximum zoom amount, always used, even if a page asks for higher. + */ +static const double MAX_ZOOM = 8.0; + +/** + * Minimum zoom amount, always used, even if a page asks for lower. + */ +static const double MIN_ZOOM = 0.125; + AsyncPanZoomController::AsyncPanZoomController(GeckoContentController* aGeckoContentController, GestureBehavior aGestures) : mGeckoContentController(aGeckoContentController), @@ -62,6 +87,13 @@ AsyncPanZoomController::AsyncPanZoomController(GeckoContentController* aGeckoCon } SetDPI(mDPI); + + if (!gComputedTimingFunction) { + gComputedTimingFunction = new ComputedTimingFunction(); + gComputedTimingFunction->Init( + nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE)); + ClearOnShutdown(&gComputedTimingFunction); + } } AsyncPanZoomController::~AsyncPanZoomController() { @@ -202,6 +234,12 @@ nsEventStatus AsyncPanZoomController::OnTouchStart(const MultiTouchInput& aEvent PRInt32 xPos = point.x, yPos = point.y; switch (mState) { + case ANIMATING_ZOOM: + // We just interrupted a double-tap animation, so force a redraw in case + // this touchstart is just a tap that doesn't end up triggering a redraw. + RequestContentRepaint(); + ScheduleComposite(); + // Fall through. case FLING: CancelAnimation(); // Fall through. @@ -231,6 +269,7 @@ nsEventStatus AsyncPanZoomController::OnTouchMove(const MultiTouchInput& aEvent) switch (mState) { case FLING: case NOTHING: + case ANIMATING_ZOOM: // May happen if the user double-taps and drags without lifting after the // second tap. Ignore the move if this happens. return nsEventStatus_eIgnore; @@ -269,6 +308,7 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent) // Should never happen. NS_WARNING("Received impossible touch end in OnTouchEnd."); // Fall through. + case ANIMATING_ZOOM: case NOTHING: // May happen if the user double-taps and drags without lifting after the // second tap. Ignore if this happens. @@ -340,14 +380,14 @@ nsEventStatus AsyncPanZoomController::OnScale(const PinchGestureInput& aEvent) { PRInt32 neededDisplacementX = 0, neededDisplacementY = 0; // Only do the scaling if we won't go over 8x zoom in or out. - bool doScale = (scale < 8.0f && spanRatio > 1.0f) || (scale > 0.125f && spanRatio < 1.0f); + bool doScale = (scale < MAX_ZOOM && spanRatio > 1.0f) || (scale > MIN_ZOOM && spanRatio < 1.0f); // If this zoom will take it over 8x zoom in either direction, but it's not // already there, then normalize it. - if (scale * spanRatio > 8.0f) { - spanRatio = scale / 8.0f; - } else if (scale * spanRatio < 0.125f) { - spanRatio = scale / 0.125f; + if (scale * spanRatio > MAX_ZOOM) { + spanRatio = scale / MAX_ZOOM; + } else if (scale * spanRatio < MIN_ZOOM) { + spanRatio = scale / MIN_ZOOM; } if (doScale) { @@ -432,7 +472,15 @@ nsEventStatus AsyncPanZoomController::OnSingleTapConfirmed(const TapGestureInput } nsEventStatus AsyncPanZoomController::OnDoubleTap(const TapGestureInput& aEvent) { - // XXX: Implement this. + if (mGeckoContentController) { + MonitorAutoLock monitor(mMonitor); + + gfx::Point point = WidgetSpaceToCompensatedViewportSpace( + gfx::Point(aEvent.mPoint.x, aEvent.mPoint.y), + mFrameMetrics.mResolution.width); + mGeckoContentController->HandleDoubleTap(nsIntPoint(NS_lround(point.x), NS_lround(point.y))); + return nsEventStatus_eConsumeNoDefault; + } return nsEventStatus_eIgnore; } @@ -570,7 +618,7 @@ void AsyncPanZoomController::SetPageRect(const gfx::Rect& aCSSPageRect) { float scale = mFrameMetrics.mResolution.width; // The page rect is the css page rect scaled by the current zoom. - pageSize.ScaleRoundOut(scale); + pageSize.ScaleRoundOut(1 / scale); // Round the page rect so we don't get any truncation, then get the nsIntRect // from this. @@ -728,9 +776,43 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa { MonitorAutoLock mon(mMonitor); - // If a fling is currently happening, apply it now. We can pull the updated - // metrics afterwards. - requestAnimationFrame = requestAnimationFrame || DoFling(aSampleTime - mLastSampleTime); + switch (mState) + { + case FLING: + // If a fling is currently happening, apply it now. We can pull the updated + // metrics afterwards. + requestAnimationFrame |= DoFling(aSampleTime - mLastSampleTime); + break; + case ANIMATING_ZOOM: { + double animPosition = (aSampleTime - mAnimationStartTime) / ZOOM_TO_DURATION; + if (animPosition > 1.0) { + animPosition = 1.0; + } + double sampledPosition = gComputedTimingFunction->GetValue(animPosition); + + mFrameMetrics.mResolution.width = mFrameMetrics.mResolution.height = + mEndZoomToMetrics.mResolution.width * sampledPosition + + mStartZoomToMetrics.mResolution.width * (1 - sampledPosition); + + mFrameMetrics.mViewportScrollOffset = nsIntPoint( + mEndZoomToMetrics.mViewportScrollOffset.x * sampledPosition + + mStartZoomToMetrics.mViewportScrollOffset.x * (1 - sampledPosition), + mEndZoomToMetrics.mViewportScrollOffset.y * sampledPosition + + mStartZoomToMetrics.mViewportScrollOffset.y * (1 - sampledPosition) + ); + + requestAnimationFrame = true; + + if (aSampleTime - mAnimationStartTime >= ZOOM_TO_DURATION) { + mState = NOTHING; + RequestContentRepaint(); + } + + break; + } + default: + break; + } // Current local transform; this is not what's painted but rather what PZC has // transformed due to touches like panning or pinching. Eventually, the root @@ -800,7 +882,7 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aViewportFr // Assuming a first paint means a new page has been loaded, clear the flag // indicating that we may have touch listeners. mMayHaveTouchListeners = false; - } else if (!mFrameMetrics.mContentRect.IsEqualEdges(aViewportFrame.mContentRect)) { + } else if (!mFrameMetrics.mCSSContentRect.IsEqualEdges(aViewportFrame.mCSSContentRect)) { mFrameMetrics.mCSSContentRect = aViewportFrame.mCSSContentRect; SetPageRect(mFrameMetrics.mCSSContentRect); } @@ -829,5 +911,79 @@ void AsyncPanZoomController::CancelDefaultPanZoom() { } } +void AsyncPanZoomController::ZoomToRect(const gfxRect& aRect) { + gfx::Rect zoomToRect(gfx::Rect(aRect.x, aRect.y, aRect.width, aRect.height)); + gfx::Rect cssPageRect = mFrameMetrics.mCSSContentRect; + + { + MonitorAutoLock mon(mMonitor); + + mState = ANIMATING_ZOOM; + + nsIntRect viewport = mFrameMetrics.mViewport; + + // If the rect is empty, treat it as a request to zoom out to the full page + // size. + if (zoomToRect.IsEmpty()) { + nsIntRect cssViewport = viewport; + cssViewport.ScaleRoundIn(1 / mFrameMetrics.mResolution.width); + cssViewport.MoveBy(mFrameMetrics.mViewportScrollOffset); + + float y = mFrameMetrics.mViewportScrollOffset.y; + float newHeight = cssViewport.height * cssPageRect.width / cssViewport.width; + float dh = cssViewport.height - newHeight; + + zoomToRect = gfx::Rect(0.0f, + y + dh/2, + cssPageRect.width, + y + dh/2 + newHeight); + } else { + float targetRatio = float(viewport.width) / float(viewport.height); + float rectRatio = zoomToRect.width / zoomToRect.height; + + if (fabsf(targetRatio - rectRatio) < EPSILON) { + // All good, do nothing. + } else if (targetRatio < rectRatio) { + // Need to increase zoomToRect height. + float newHeight = zoomToRect.height / targetRatio; + zoomToRect.y -= (newHeight - zoomToRect.height) / 2; + zoomToRect.height = newHeight; + } else { // (targetRatio > rectRatio) { + // Need to increase zoomToRect width. + float newWidth = targetRatio * zoomToRect.width; + zoomToRect.x -= (newWidth - zoomToRect.width) / 2; + zoomToRect.width = newWidth; + } + + zoomToRect = zoomToRect.Intersect(cssPageRect); + } + + mEndZoomToMetrics.mResolution.width = mEndZoomToMetrics.mResolution.height = + NS_MIN(viewport.width / zoomToRect.width, viewport.height / zoomToRect.height); + + mEndZoomToMetrics.mResolution.width = mEndZoomToMetrics.mResolution.height = + clamped(mEndZoomToMetrics.mResolution.width, MIN_ZOOM, MAX_ZOOM); + + // Recalculate the zoom to rect using the new dimensions. + zoomToRect.width = viewport.width / mEndZoomToMetrics.mResolution.width; + zoomToRect.height = viewport.height / mEndZoomToMetrics.mResolution.height; + + // Clamp the zoom to rect to the CSS rect to make sure it fits. + zoomToRect = zoomToRect.Intersect(cssPageRect); + + // Do one final recalculation to get the resolution. + mEndZoomToMetrics.mResolution.width = mEndZoomToMetrics.mResolution.height = + NS_MAX(viewport.width / zoomToRect.width, viewport.height / zoomToRect.height); + + mStartZoomToMetrics = mFrameMetrics; + mEndZoomToMetrics.mViewportScrollOffset = + nsIntPoint(NS_lround(zoomToRect.x), NS_lround(zoomToRect.y)); + + mAnimationStartTime = TimeStamp::Now(); + + ScheduleComposite(); + } +} + } } diff --git a/gfx/layers/ipc/AsyncPanZoomController.h b/gfx/layers/ipc/AsyncPanZoomController.h index 17956ad090e9..efe65c4e4d49 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.h +++ b/gfx/layers/ipc/AsyncPanZoomController.h @@ -119,6 +119,13 @@ public: */ void CancelDefaultPanZoom(); + /** + * Kicks an animation to zoom to a rect. This may be either a zoom out or zoom + * in. The actual animation is done on the compositor thread after being set + * up. |aRect| must be given in CSS pixels, relative to the document. + */ + void ZoomToRect(const gfxRect& aRect); + // -------------------------------------------------------------------------- // These methods must only be called on the compositor thread. // @@ -355,6 +362,7 @@ private: TOUCHING, /* one touch-start event received */ PANNING, /* panning without axis lock */ PINCHING, /* nth touch-start, where n > 1. this mode allows pan and zoom */ + ANIMATING_ZOOM /* animated zoom to a new rect */ }; enum ContentPainterStatus { @@ -383,14 +391,26 @@ private: // Both |mFrameMetrics| and |mLastContentPaintMetrics| are protected by the // monitor. Do not read from or modify either of them without locking. FrameMetrics mFrameMetrics; + // These are the metrics at last content paint, the most recent // values we were notified of in NotifyLayersUpdate(). FrameMetrics mLastContentPaintMetrics; + // The last metrics that we requested a paint for. These are used to make sure // that we're not requesting a paint of the same thing that's already drawn. // If we don't do this check, we don't get a ShadowLayersUpdated back. FrameMetrics mLastPaintRequestMetrics; + // Old metrics from before we started a zoom animation. This is only valid + // when we are in the "ANIMATED_ZOOM" state. This is used so that we can + // interpolate between the start and end frames. We only use the + // |mViewportScrollOffset| and |mResolution| fields on this. + FrameMetrics mStartZoomToMetrics; + // Target metrics for a zoom to animation. This is only valid when we are in + // the "ANIMATED_ZOOM" state. We only use the |mViewportScrollOffset| and + // |mResolution| fields on this. + FrameMetrics mEndZoomToMetrics; + AxisX mX; AxisY mY; @@ -402,6 +422,10 @@ private: // The last time a touch event came through on the UI thread. PRInt32 mLastEventTime; + // Start time of an animation. This is used for a zoom to animation to mark + // the beginning. + TimeStamp mAnimationStartTime; + // Stores the previous focus point if there is a pinch gesture happening. Used // to allow panning by moving multiple fingers (thus moving the focus point). nsIntPoint mLastZoomFocus; diff --git a/gfx/layers/ipc/GeckoContentController.h b/gfx/layers/ipc/GeckoContentController.h index 5c520a2564a0..66a7b5762b64 100644 --- a/gfx/layers/ipc/GeckoContentController.h +++ b/gfx/layers/ipc/GeckoContentController.h @@ -23,6 +23,14 @@ public: */ virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics) = 0; + /** + * Requests handling of a double tap. |aPoint| is in CSS pixels, relative to + * the current scroll offset. This should eventually round-trip back to + * AsyncPanZoomController::ZoomToRect with the dimensions that we want to zoom + * to. + */ + virtual void HandleDoubleTap(const nsIntPoint& aPoint) = 0; + GeckoContentController() {} virtual ~GeckoContentController() {} }; diff --git a/ipc/glue/IPCMessageUtils.h b/ipc/glue/IPCMessageUtils.h index f86fee9d05a3..c13e27880baa 100644 --- a/ipc/glue/IPCMessageUtils.h +++ b/ipc/glue/IPCMessageUtils.h @@ -23,11 +23,13 @@ #include "gfxMatrix.h" #include "gfxPattern.h" #include "gfxPoint.h" +#include "gfxRect.h" #include "nsRect.h" #include "nsRegion.h" #include "gfxASurface.h" #include "jsapi.h" #include "LayersTypes.h" +#include "FrameMetrics.h" #ifdef _MSC_VER #pragma warning( disable : 4800 ) @@ -517,6 +519,28 @@ struct ParamTraits } }; +template<> +struct ParamTraits +{ + typedef gfxRect paramType; + + static void Write(Message* aMsg, const paramType& aParam) + { + WriteParam(aMsg, aParam.x); + WriteParam(aMsg, aParam.y); + WriteParam(aMsg, aParam.width); + WriteParam(aMsg, aParam.height); + } + + static bool Read(const Message* aMsg, void** aIter, paramType* aResult) + { + return ReadParam(aMsg, aIter, &aResult->x) && + ReadParam(aMsg, aIter, &aResult->y) && + ReadParam(aMsg, aIter, &aResult->width) && + ReadParam(aMsg, aIter, &aResult->height); + } +}; + template<> struct ParamTraits { diff --git a/layout/ipc/RenderFrameParent.cpp b/layout/ipc/RenderFrameParent.cpp index 33ed541a0072..34ba23b8372d 100644 --- a/layout/ipc/RenderFrameParent.cpp +++ b/layout/ipc/RenderFrameParent.cpp @@ -492,6 +492,23 @@ public: } } + virtual void HandleDoubleTap(const nsIntPoint& aPoint) MOZ_OVERRIDE + { + if (MessageLoop::current() != mUILoop) { + // We have to send this message from the "UI thread" (main + // thread). + mUILoop->PostTask( + FROM_HERE, + NewRunnableMethod(this, &RemoteContentController::HandleDoubleTap, + aPoint)); + return; + } + if (mRenderFrame) { + TabParent* browser = static_cast(mRenderFrame->Manager()); + browser->HandleDoubleTap(aPoint); + } + } + void ClearRenderFrame() { mRenderFrame = nullptr; } private: @@ -869,6 +886,14 @@ RenderFrameParent::NotifyDOMTouchListenerAdded() } } +void +RenderFrameParent::ZoomToRect(const gfxRect& aRect) +{ + if (mPanZoomController) { + mPanZoomController->ZoomToRect(aRect); + } +} + } // namespace layout } // namespace mozilla diff --git a/layout/ipc/RenderFrameParent.h b/layout/ipc/RenderFrameParent.h index 57d5587f6520..36993e5d08fa 100644 --- a/layout/ipc/RenderFrameParent.h +++ b/layout/ipc/RenderFrameParent.h @@ -95,6 +95,8 @@ public: void NotifyDOMTouchListenerAdded(); + void ZoomToRect(const gfxRect& aRect); + protected: void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE; From 15c8e89958e1acf4ab2cde9a1c2911dee81342c7 Mon Sep 17 00:00:00 2001 From: Doug Sherk Date: Tue, 7 Aug 2012 18:51:10 -0700 Subject: [PATCH 104/169] Bug 775463: Implement tolerance in double tap detection r=cjones --- gfx/layers/ipc/AsyncPanZoomController.cpp | 8 +++++++- gfx/layers/ipc/AsyncPanZoomController.h | 14 ++++++++++++++ gfx/layers/ipc/GestureEventListener.cpp | 12 +++++++++--- gfx/layers/ipc/GestureEventListener.h | 12 ++++++++---- 4 files changed, 38 insertions(+), 8 deletions(-) diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index 6d5c3fd40215..f927c949e31d 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -24,6 +24,8 @@ using namespace mozilla::css; namespace mozilla { namespace layers { +const float AsyncPanZoomController::TOUCH_START_TOLERANCE = 1.0f/16.0f; + static const float EPSILON = 0.0001; /** @@ -275,8 +277,8 @@ nsEventStatus AsyncPanZoomController::OnTouchMove(const MultiTouchInput& aEvent) return nsEventStatus_eIgnore; case TOUCHING: { - float panThreshold = 1.0f/2.0f * mDPI; UpdateWithTouchAtDevicePoint(aEvent); + float panThreshold = TOUCH_START_TOLERANCE * mDPI; if (PanDistance() < panThreshold) { return nsEventStatus_eIgnore; } @@ -723,6 +725,10 @@ void AsyncPanZoomController::SetDPI(int aDPI) { mDPI = aDPI; } +int AsyncPanZoomController::GetDPI() { + return mDPI; +} + void AsyncPanZoomController::ScheduleComposite() { if (mCompositorParent) { mCompositorParent->ScheduleRenderOnCompositorThread(); diff --git a/gfx/layers/ipc/AsyncPanZoomController.h b/gfx/layers/ipc/AsyncPanZoomController.h index efe65c4e4d49..f8b4ea4953c6 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.h +++ b/gfx/layers/ipc/AsyncPanZoomController.h @@ -57,6 +57,14 @@ public: USE_GESTURE_DETECTOR }; + /** + * Constant describing the tolerance in distance we use, multiplied by the + * device DPI, before we start panning the screen. This is to prevent us from + * accidentally processing taps as touch moves, and from very short/accidental + * touches moving the screen. + */ + static const float TOUCH_START_TOLERANCE; + AsyncPanZoomController(GeckoContentController* aController, GestureBehavior aGestures = DEFAULT_GESTURES); ~AsyncPanZoomController(); @@ -179,6 +187,12 @@ public: */ void SetDPI(int aDPI); + /** + * Gets the DPI of the device for use outside the panning and zooming logic. + * It defaults to 72 if not set using SetDPI() at any point. + */ + int GetDPI(); + protected: /** * Helper method for touches beginning. Sets everything up for panning and any diff --git a/gfx/layers/ipc/GestureEventListener.cpp b/gfx/layers/ipc/GestureEventListener.cpp index e3a338934222..3bc50b1f51e8 100644 --- a/gfx/layers/ipc/GestureEventListener.cpp +++ b/gfx/layers/ipc/GestureEventListener.cpp @@ -63,6 +63,7 @@ nsEventStatus GestureEventListener::HandleInputEvent(const InputData& aEvent) size_t length = mTouches.Length(); if (length == 1) { mTapStartTime = event.mTime; + mTouchStartPosition = event.mTouches[0].mScreenPoint; if (mState == GESTURE_NONE) { mState = GESTURE_WAITING_SINGLE_TAP; } @@ -74,9 +75,14 @@ nsEventStatus GestureEventListener::HandleInputEvent(const InputData& aEvent) break; } case MultiTouchInput::MULTITOUCH_MOVE: { - // If we move at all, just bail out of the tap. We need to change this so - // that there's some tolerance in the future. - HandleTapCancel(event); + // If we move too much, bail out of the tap. + nsIntPoint touch = (nsIntPoint&)event.mTouches[0].mScreenPoint; + if (mTouches.Length() == 1 && + NS_hypot(mTouchStartPosition.x - touch.x, mTouchStartPosition.y - touch.y) > + mAsyncPanZoomController->GetDPI() * AsyncPanZoomController::TOUCH_START_TOLERANCE) + { + HandleTapCancel(event); + } bool foundAlreadyExistingTouch = false; for (size_t i = 0; i < mTouches.Length(); i++) { diff --git a/gfx/layers/ipc/GestureEventListener.h b/gfx/layers/ipc/GestureEventListener.h index e715e2020760..f1fced0f046d 100644 --- a/gfx/layers/ipc/GestureEventListener.h +++ b/gfx/layers/ipc/GestureEventListener.h @@ -1,7 +1,4 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set sw=4 ts=8 et tw=80 : */ -/* 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 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set sw=4 ts=8 et tw=80 : */ /* 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/. */ #ifndef mozilla_layers_GestureEventListener_h @@ -170,6 +167,13 @@ protected: * we can cancel it if a double tap actually comes in. */ CancelableTask *mDoubleTapTimeoutTask; + + /** + * Position of the last touch starting. This is only valid during an attempt + * to determine if a touch is a tap. This means that it is used in both the + * "GESTURE_WAITING_SINGLE_TAP" and "GESTURE_WAITING_DOUBLE_TAP" states. + */ + nsIntPoint mTouchStartPosition; }; } From 7c76836746dcefa6a6fce98790ba7d14d4da4658 Mon Sep 17 00:00:00 2001 From: Doug Sherk Date: Tue, 7 Aug 2012 18:51:11 -0700 Subject: [PATCH 105/169] Bug 779572: Factor zoom into min pan distance before moving the viewport r=cjones --- gfx/layers/ipc/AsyncPanZoomController.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index f927c949e31d..c40bdd75476b 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -277,12 +277,15 @@ nsEventStatus AsyncPanZoomController::OnTouchMove(const MultiTouchInput& aEvent) return nsEventStatus_eIgnore; case TOUCHING: { - UpdateWithTouchAtDevicePoint(aEvent); float panThreshold = TOUCH_START_TOLERANCE * mDPI; + UpdateWithTouchAtDevicePoint(aEvent); + if (PanDistance() < panThreshold) { return nsEventStatus_eIgnore; } + StartPanning(aEvent); + return nsEventStatus_eConsumeNoDefault; } @@ -492,7 +495,8 @@ nsEventStatus AsyncPanZoomController::OnCancelTap(const TapGestureInput& aEvent) } float AsyncPanZoomController::PanDistance() { - return NS_hypot(mX.PanDistance(), mY.PanDistance()) * mFrameMetrics.mResolution.width; + MonitorAutoLock monitor(mMonitor); + return NS_hypot(mX.PanDistance(), mY.PanDistance()); } const nsPoint AsyncPanZoomController::GetVelocityVector() { From 31ad905e49d5fa0c16c7f2610d58446e6378ace9 Mon Sep 17 00:00:00 2001 From: Doug Sherk Date: Tue, 7 Aug 2012 18:51:13 -0700 Subject: [PATCH 106/169] Bug 779572: Properly protect state in AsyncPanZoomController with a monitor r=cjones --- gfx/layers/ipc/AsyncPanZoomController.cpp | 30 ++++++++++++++--------- gfx/layers/ipc/AsyncPanZoomController.h | 17 +++++++++++++ 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index c40bdd75476b..626f50a8eb4d 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -243,12 +243,15 @@ nsEventStatus AsyncPanZoomController::OnTouchStart(const MultiTouchInput& aEvent ScheduleComposite(); // Fall through. case FLING: - CancelAnimation(); + { + MonitorAutoLock monitor(mMonitor); + CancelAnimation(); + } // Fall through. case NOTHING: mX.StartTouch(xPos); mY.StartTouch(yPos); - mState = TOUCHING; + SetState(TOUCHING); break; case TOUCHING: case PANNING: @@ -320,7 +323,7 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent) return nsEventStatus_eIgnore; case TOUCHING: - mState = NOTHING; + SetState(NOTHING); return nsEventStatus_eIgnore; case PANNING: @@ -329,10 +332,10 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent) ScheduleComposite(); RequestContentRepaint(); } - mState = FLING; + SetState(FLING); return nsEventStatus_eConsumeNoDefault; case PINCHING: - mState = NOTHING; + SetState(NOTHING); // Scale gesture listener should have handled this. NS_WARNING("Gesture listener should have handled pinching in OnTouchEnd."); return nsEventStatus_eIgnore; @@ -342,12 +345,12 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent) } nsEventStatus AsyncPanZoomController::OnTouchCancel(const MultiTouchInput& aEvent) { - mState = NOTHING; + SetState(NOTHING); return nsEventStatus_eConsumeNoDefault; } nsEventStatus AsyncPanZoomController::OnScaleBegin(const PinchGestureInput& aEvent) { - mState = PINCHING; + SetState(PINCHING); mLastZoomFocus = aEvent.mFocusPoint; return nsEventStatus_eConsumeNoDefault; @@ -449,7 +452,7 @@ nsEventStatus AsyncPanZoomController::OnScale(const PinchGestureInput& aEvent) { } nsEventStatus AsyncPanZoomController::OnScaleEnd(const PinchGestureInput& aEvent) { - mState = PANNING; + SetState(PANNING); mX.StartTouch(aEvent.mFocusPoint.x); mY.StartTouch(aEvent.mFocusPoint.y); { @@ -517,7 +520,7 @@ void AsyncPanZoomController::StartPanning(const MultiTouchInput& aEvent) { mX.StartTouch(touch.mScreenPoint.x); mY.StartTouch(touch.mScreenPoint.y); - mState = PANNING; + SetState(PANNING); if (angle < AXIS_LOCK_ANGLE || angle > (M_PI - AXIS_LOCK_ANGLE)) { mY.LockPanning(); @@ -925,11 +928,11 @@ void AsyncPanZoomController::ZoomToRect(const gfxRect& aRect) { gfx::Rect zoomToRect(gfx::Rect(aRect.x, aRect.y, aRect.width, aRect.height)); gfx::Rect cssPageRect = mFrameMetrics.mCSSContentRect; + SetState(ANIMATING_ZOOM); + { MonitorAutoLock mon(mMonitor); - mState = ANIMATING_ZOOM; - nsIntRect viewport = mFrameMetrics.mViewport; // If the rect is empty, treat it as a request to zoom out to the full page @@ -995,5 +998,10 @@ void AsyncPanZoomController::ZoomToRect(const gfxRect& aRect) { } } +void AsyncPanZoomController::SetState(PanZoomState aState) { + MonitorAutoLock monitor(mMonitor); + mState = aState; +} + } } diff --git a/gfx/layers/ipc/AsyncPanZoomController.h b/gfx/layers/ipc/AsyncPanZoomController.h index f8b4ea4953c6..549b24629e93 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.h +++ b/gfx/layers/ipc/AsyncPanZoomController.h @@ -296,6 +296,8 @@ protected: * Cancels any currently running animation. Note that all this does is set the * state of the AsyncPanZoomController back to NOTHING, but it is the * animation's responsibility to check this before advancing. + * + * *** The monitor must be held while calling this. */ void CancelAnimation(); @@ -398,6 +400,13 @@ private: CONTENT_PAINTING_AND_PAINT_PENDING }; + /** + * Helper to set the current state. Holds the monitor before actually setting + * it. If the monitor is already held by the current thread, it is safe to + * instead use: |mState = NEWSTATE;| + */ + void SetState(PanZoomState aState); + nsRefPtr mCompositorParent; nsRefPtr mGeckoContentController; nsRefPtr mGestureEventListener; @@ -428,6 +437,10 @@ private: AxisX mX; AxisY mY; + // Protects |mFrameMetrics|, |mLastContentPaintMetrics| and |mState|. Before + // manipulating |mFrameMetrics| or |mLastContentPaintMetrics|, the monitor + // should be held. When setting |mState|, either the SetState() function can + // be used, or the monitor can be held and then |mState| updated. Monitor mMonitor; // The last time the compositor has sampled the content transform for this @@ -443,7 +456,11 @@ private: // Stores the previous focus point if there is a pinch gesture happening. Used // to allow panning by moving multiple fingers (thus moving the focus point). nsIntPoint mLastZoomFocus; + + // Stores the state of panning and zooming this frame. This is protected by + // |mMonitor|; that is, it should be held whenever this is updated. PanZoomState mState; + int mDPI; // Stores the current paint status of the frame that we're managing. Repaints From de6acfbf971448fe362fbcafc4828e20c65ecafe Mon Sep 17 00:00:00 2001 From: Doug Sherk Date: Tue, 7 Aug 2012 18:51:15 -0700 Subject: [PATCH 107/169] Bug 775451: Reduce diagonal checkerboarding r=cjones --- gfx/layers/ipc/AsyncPanZoomController.cpp | 55 ++++++++++++++--------- gfx/layers/ipc/AsyncPanZoomController.h | 13 +++++- 2 files changed, 45 insertions(+), 23 deletions(-) diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index 626f50a8eb4d..a2b3a33dda78 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -502,11 +502,8 @@ float AsyncPanZoomController::PanDistance() { return NS_hypot(mX.PanDistance(), mY.PanDistance()); } -const nsPoint AsyncPanZoomController::GetVelocityVector() { - return nsPoint( - mX.GetVelocity(), - mY.GetVelocity() - ); +const gfx::Point AsyncPanZoomController::GetVelocityVector() { + return gfx::Point(mX.GetVelocity(), mY.GetVelocity()); } void AsyncPanZoomController::StartPanning(const MultiTouchInput& aEvent) { @@ -660,13 +657,30 @@ void AsyncPanZoomController::ScaleWithFocus(float aScale, const nsIntPoint& aFoc mFrameMetrics = metrics; } +bool AsyncPanZoomController::EnlargeDisplayPortAlongAxis(float aViewport, + float aVelocity, + float* aDisplayPortOffset, + float* aDisplayPortLength) +{ + const float MIN_SKATE_SIZE_MULTIPLIER = 2.0f; + const float MAX_SKATE_SIZE_MULTIPLIER = 4.0f; + + if (fabsf(aVelocity) > MIN_SKATE_SPEED) { + *aDisplayPortLength = aViewport * clamped(fabsf(aVelocity), + MIN_SKATE_SIZE_MULTIPLIER, MAX_SKATE_SIZE_MULTIPLIER); + *aDisplayPortOffset = aVelocity > 0 ? 0 : aViewport - *aDisplayPortLength; + return true; + } + return false; +} + const nsIntRect AsyncPanZoomController::CalculatePendingDisplayPort() { float scale = mFrameMetrics.mResolution.width; nsIntRect viewport = mFrameMetrics.mViewport; viewport.ScaleRoundIn(1 / scale); nsIntPoint scrollOffset = mFrameMetrics.mViewportScrollOffset; - nsPoint velocity = GetVelocityVector(); + gfx::Point velocity = GetVelocityVector(); // The displayport is relative to the current scroll offset. Here's a little // diagram to make it easier to see: @@ -693,28 +707,25 @@ const nsIntRect AsyncPanZoomController::CalculatePendingDisplayPort() { // and far top, it is clear that this distance is 1/4 of the displayport's // height/width dimension. const float STATIONARY_SIZE_MULTIPLIER = 2.0f; - const float SKATE_SIZE_MULTIPLIER = 3.0f; gfx::Rect displayPort(0, 0, viewport.width * STATIONARY_SIZE_MULTIPLIER, viewport.height * STATIONARY_SIZE_MULTIPLIER); - // Iff there's motion along only one axis of movement, and it's above a - // threshold, then we want to paint a larger area in the direction of that - // motion so that it's less likely to checkerboard. Also note that the other - // axis doesn't need its displayport enlarged beyond the viewport dimension, - // since it is impossible for it to checkerboard along that axis until motion - // begins on it. - if (fabsf(velocity.x) > MIN_SKATE_SPEED && fabsf(velocity.y) < MIN_SKATE_SPEED) { - displayPort.height = viewport.height; - displayPort.width = viewport.width * SKATE_SIZE_MULTIPLIER; - displayPort.x = velocity.x > 0 ? 0 : viewport.width - displayPort.width; - } else if (fabsf(velocity.x) < MIN_SKATE_SPEED && fabsf(velocity.y) > MIN_SKATE_SPEED) { - displayPort.width = viewport.width; - displayPort.height = viewport.height * SKATE_SIZE_MULTIPLIER; - displayPort.y = velocity.y > 0 ? 0 : viewport.height - displayPort.height; - } else { + // If there's motion along an axis of movement, and it's above a threshold, + // then we want to paint a larger area in the direction of that motion so that + // it's less likely to checkerboard. + bool enlargedX = EnlargeDisplayPortAlongAxis( + viewport.width, velocity.x, &displayPort.x, &displayPort.width); + bool enlargedY = EnlargeDisplayPortAlongAxis( + viewport.height, velocity.y, &displayPort.y, &displayPort.height); + + if (!enlargedX && !enlargedY) { displayPort.x = -displayPort.width / 4; displayPort.y = -displayPort.height / 4; + } else if (!enlargedX) { + displayPort.width = viewport.width; + } else if (!enlargedY) { + displayPort.height = viewport.height; } gfx::Rect shiftedDisplayPort = displayPort; diff --git a/gfx/layers/ipc/AsyncPanZoomController.h b/gfx/layers/ipc/AsyncPanZoomController.h index 549b24629e93..ac825bf46fa7 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.h +++ b/gfx/layers/ipc/AsyncPanZoomController.h @@ -312,7 +312,7 @@ protected: /** * Gets a vector of the velocities of each axis. */ - const nsPoint GetVelocityVector(); + const gfx::Point GetVelocityVector(); /** * Gets a reference to the first SingleTouchData from a MultiTouchInput. This @@ -347,6 +347,17 @@ protected: */ const nsIntRect CalculatePendingDisplayPort(); + /** + * Attempts to enlarge the displayport along a single axis. Returns whether or + * not the displayport was enlarged. This will fail in circumstances where the + * velocity along that axis is not high enough to need any changes. The + * displayport metrics are expected to be passed into |aDisplayPortOffset| and + * |aDisplayPortLength|. If enlarged, these will be updated with the new + * metrics. + */ + bool EnlargeDisplayPortAlongAxis(float aViewport, float aVelocity, + float* aDisplayPortOffset, float* aDisplayPortLength); + /** * Utility function to send updated FrameMetrics to Gecko so that it can paint * the displayport area. Calls into GeckoContentController to do the actual From 8bfb3ca8f7d11327477866b78427db90d7005c60 Mon Sep 17 00:00:00 2001 From: Doug Sherk Date: Tue, 7 Aug 2012 19:18:53 -0700 Subject: [PATCH 108/169] Bug 777463: Fix bustage, no r=me --- dom/ipc/TabChild.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index e0b9a8ba0846..a6e71ee665d8 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -131,10 +131,9 @@ TabChild::Observe(nsISupports *aSubject, nsCOMPtr tabChild(GetTabChildFrom(docShell)); if (tabChild == this) { gfxRect rect; - int numAssigned = sscanf(NS_ConvertUTF16toUTF8(aData).get(), - "{\"x\":%lf,\"y\":%lf,\"w\":%lf,\"h\":%lf}", - &rect.x, &rect.y, &rect.width, &rect.height); - MOZ_ASSERT(numAssigned == 4, "Invalid JSON format"); + sscanf(NS_ConvertUTF16toUTF8(aData).get(), + "{\"x\":%lf,\"y\":%lf,\"w\":%lf,\"h\":%lf}", + &rect.x, &rect.y, &rect.width, &rect.height); SendZoomToRect(rect); } } From 0bef654a22d8b93d26cb253b8075f30839993c06 Mon Sep 17 00:00:00 2001 From: Phil Ringnalda Date: Tue, 7 Aug 2012 20:40:48 -0700 Subject: [PATCH 109/169] Backout 8b3b879bc63f (Bug 777463), 32cc8084d1b7 (Bug 775451), ce9014442e13:4d52cfac7c37 (Bug 779572), b33f2b2dbbc5:963aed158547 (Bug 775463), 36832ad5ea65 (Bug 780210), 10695750e4e9:a2afc5b5e538 (Bug 775448), c9f42eebd694 (Bug 775447) for Linux bustage --- .../BrowserElementScrolling.js | 192 +---------- dom/ipc/PBrowser.ipdl | 27 +- dom/ipc/TabChild.cpp | 141 ++------ dom/ipc/TabChild.h | 19 +- dom/ipc/TabParent.cpp | 28 +- dom/ipc/TabParent.h | 3 - gfx/layers/ipc/AsyncPanZoomController.cpp | 310 +++--------------- gfx/layers/ipc/AsyncPanZoomController.h | 96 +----- gfx/layers/ipc/GeckoContentController.h | 8 - gfx/layers/ipc/GestureEventListener.cpp | 17 +- gfx/layers/ipc/GestureEventListener.h | 19 +- ipc/glue/IPCMessageUtils.h | 24 -- layout/ipc/PRenderFrame.ipdl | 2 - layout/ipc/RenderFrameChild.cpp | 6 - layout/ipc/RenderFrameChild.h | 2 - layout/ipc/RenderFrameParent.cpp | 42 --- layout/ipc/RenderFrameParent.h | 6 - 17 files changed, 110 insertions(+), 832 deletions(-) diff --git a/dom/browser-element/BrowserElementScrolling.js b/dom/browser-element/BrowserElementScrolling.js index 03b815d9379c..c17f27daddaa 100644 --- a/dom/browser-element/BrowserElementScrolling.js +++ b/dom/browser-element/BrowserElementScrolling.js @@ -9,7 +9,6 @@ const ContentPanning = { }); addMessageListener("Viewport:Change", this._recvViewportChange.bind(this)); - addMessageListener("Gesture:DoubleTap", this._recvDoubleTap.bind(this)); }, handleEvent: function cp_handleEvent(evt) { @@ -44,16 +43,6 @@ const ContentPanning = { let oldTarget = this.target; [this.target, this.scrollCallback] = this.getPannable(evt.target); - // If we found a target, that means we have found a scrollable subframe. In - // this case, and if we are using async panning and zooming on the parent - // frame, inform the pan/zoom controller that it should not attempt to - // handle any touch events it gets until the next batch (meaning the next - // time we get a touch end). - if (this.target != null && ContentPanning._asyncPanZoomForViewportFrame) { - var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); - os.notifyObservers(docShell, 'cancel-default-pan-zoom', null); - } - // If there is a pan animation running (from a previous pan gesture) and // the user touch back the screen, stop this animation immediatly and // prevent the possible click action if the touch happens on the same @@ -197,34 +186,21 @@ const ContentPanning = { }, _recvViewportChange: function(data) { - let metrics = data.json; - let displayPort = metrics.displayPort; + let viewport = data.json; + let displayPort = viewport.displayPort; - let screenWidth = metrics.screenSize.width; - let screenHeight = metrics.screenSize.height; + let screenWidth = viewport.screenSize.width; + let screenHeight = viewport.screenSize.height; - let x = metrics.x; - let y = metrics.y; - - this._zoom = metrics.zoom; - this._viewport = new Rect(x, y, - screenWidth / metrics.zoom, - screenHeight / metrics.zoom); - this._cssPageRect = new Rect(metrics.cssPageRect.x, - metrics.cssPageRect.y, - metrics.cssPageRect.width, - metrics.cssPageRect.height); + let x = viewport.x; + let y = viewport.y; let cwu = content.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils); - if (this._screenWidth != screenWidth || this._screenHeight != screenHeight) { - cwu.setCSSViewport(screenWidth, screenHeight); - this._screenWidth = screenWidth; - this._screenHeight = screenHeight; - } + cwu.setCSSViewport(screenWidth, screenHeight); // Set scroll position cwu.setScrollPositionClampingScrollPortSize( - screenWidth / metrics.zoom, screenHeight / metrics.zoom); + screenWidth / viewport.zoom, screenHeight / viewport.zoom); content.scrollTo(x, y); cwu.setResolution(displayPort.resolution, displayPort.resolution); @@ -236,109 +212,6 @@ const ContentPanning = { displayPort.height, element); } - }, - - _recvDoubleTap: function(data) { - let data = data.json; - - // We haven't received a metrics update yet; don't do anything. - if (this._viewport == null) { - return; - } - - let win = content; - - let zoom = this._zoom; - let element = ElementTouchHelper.anyElementFromPoint(win, data.x, data.y); - if (!element) { - this._zoomOut(); - return; - } - - while (element && !this._shouldZoomToElement(element)) - element = element.parentNode; - - if (!element) { - this._zoomOut(); - } else { - const margin = 15; - let rect = ElementTouchHelper.getBoundingContentRect(element); - - let cssPageRect = this._cssPageRect; - let viewport = this._viewport; - let bRect = new Rect(Math.max(cssPageRect.left, rect.x - margin), - rect.y, - rect.w + 2 * margin, - rect.h); - // constrict the rect to the screen's right edge - bRect.width = Math.min(bRect.width, cssPageRect.right - bRect.x); - - // if the rect is already taking up most of the visible area and is stretching the - // width of the page, then we want to zoom out instead. - if (this._isRectZoomedIn(bRect, viewport)) { - this._zoomOut(); - return; - } - - rect.x = Math.round(bRect.x); - rect.y = Math.round(bRect.y); - rect.w = Math.round(bRect.width); - rect.h = Math.round(Math.min(bRect.width * viewport.height / viewport.height, bRect.height)); - - // if the block we're zooming to is really tall, and the user double-tapped - // more than a screenful of height from the top of it, then adjust the y-coordinate - // so that we center the actual point the user double-tapped upon. this prevents - // flying to the top of a page when double-tapping to zoom in (bug 761721). - // the 1.2 multiplier is just a little fuzz to compensate for bRect including horizontal - // margins but not vertical ones. - let cssTapY = viewport.y + data.y; - if ((bRect.height > rect.h) && (cssTapY > rect.y + (rect.h * 1.2))) { - rect.y = cssTapY - (rect.h / 2); - } - - var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); - os.notifyObservers(docShell, 'browser-zoom-to-rect', JSON.stringify(rect)); - } - }, - - _shouldZoomToElement: function(aElement) { - let win = aElement.ownerDocument.defaultView; - if (win.getComputedStyle(aElement, null).display == "inline") - return false; - if (aElement instanceof Ci.nsIDOMHTMLLIElement) - return false; - if (aElement instanceof Ci.nsIDOMHTMLQuoteElement) - return false; - return true; - }, - - _zoomOut: function() { - let rect = new Rect(0, 0, 0, 0); - var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); - os.notifyObservers(docShell, 'browser-zoom-to-rect', JSON.stringify(rect)); - }, - - _isRectZoomedIn: function(aRect, aViewport) { - // This function checks to see if the area of the rect visible in the - // viewport (i.e. the "overlapArea" variable below) is approximately - // the max area of the rect we can show. It also checks that the rect - // is actually on-screen by testing the left and right edges of the rect. - // In effect, this tells us whether or not zooming in to this rect - // will significantly change what the user is seeing. - const minDifference = -20; - const maxDifference = 20; - - let vRect = new Rect(aViewport.x, aViewport.y, aViewport.width, aViewport.height); - let overlap = vRect.intersect(aRect); - let overlapArea = overlap.width * overlap.height; - let availHeight = Math.min(aRect.width * vRect.height / vRect.width, aRect.height); - let showing = overlapArea / (aRect.width * availHeight); - let dw = (aRect.width - vRect.width); - let dx = (aRect.x - vRect.x); - - return (showing > 0.9 && - dx > minDifference && dx < maxDifference && - dw > minDifference && dw < maxDifference); } }; @@ -512,52 +385,3 @@ const KineticPanning = { content.mozRequestAnimationFrame(callback); } }; - -const ElementTouchHelper = { - anyElementFromPoint: function(aWindow, aX, aY) { - let cwu = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils); - let elem = cwu.elementFromPoint(aX, aY, true, true); - - let HTMLIFrameElement = Ci.nsIDOMHTMLIFrameElement; - let HTMLFrameElement = Ci.nsIDOMHTMLFrameElement; - while (elem && (elem instanceof HTMLIFrameElement || elem instanceof HTMLFrameElement)) { - let rect = elem.getBoundingClientRect(); - aX -= rect.left; - aY -= rect.top; - cwu = elem.contentDocument.defaultView.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils); - elem = cwu.elementFromPoint(aX, aY, true, true); - } - - return elem; - }, - - getBoundingContentRect: function(aElement) { - if (!aElement) - return {x: 0, y: 0, w: 0, h: 0}; - - let document = aElement.ownerDocument; - while (document.defaultView.frameElement) - document = document.defaultView.frameElement.ownerDocument; - - let cwu = document.defaultView.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils); - let scrollX = {}, scrollY = {}; - cwu.getScrollXY(false, scrollX, scrollY); - - let r = aElement.getBoundingClientRect(); - - // step out of iframes and frames, offsetting scroll values - for (let frame = aElement.ownerDocument.defaultView; frame.frameElement && frame != content; frame = frame.parent) { - // adjust client coordinates' origin to be top left of iframe viewport - let rect = frame.frameElement.getBoundingClientRect(); - let left = frame.getComputedStyle(frame.frameElement, "").borderLeftWidth; - let top = frame.getComputedStyle(frame.frameElement, "").borderTopWidth; - scrollX.value += rect.left + parseInt(left); - scrollY.value += rect.top + parseInt(top); - } - - return {x: r.left + scrollX.value, - y: r.top + scrollY.value, - w: r.width, - h: r.height }; - } -}; diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl index ae5be9649083..d45ff2ff39b4 100644 --- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -15,9 +15,6 @@ include protocol POfflineCacheUpdate; include protocol PIndexedDB; include "gfxMatrix.h"; -include "gfxRect.h"; -include "gfxipc/ShadowLayerUtils.h"; -include "FrameMetrics.h"; include "IPC/nsGUIEventIPC.h"; include "mozilla/dom/TabMessageUtils.h"; include "mozilla/layout/RenderFrameUtils.h"; @@ -27,9 +24,7 @@ include DOMTypes; using IPC::URI; using gfxMatrix; -using gfxRect; using gfxSize; -using mozilla::layers::FrameMetrics; using mozilla::layers::LayersBackend; using mozilla::layout::ScrollingBehavior; using mozilla::WindowsHandle; @@ -237,14 +232,6 @@ parent: nsString aName, nsString aFeatures) returns (bool windowOpened); - NotifyDOMTouchListenerAdded(); - - /** - * Instructs the TabParent to forward a request to zoom to a rect given in - * CSS pixels. This rect is relative to the document. - */ - ZoomToRect(gfxRect aRect); - __delete__(); child: @@ -263,14 +250,10 @@ child: UpdateDimensions(nsRect rect, nsIntSize size); - UpdateFrame(FrameMetrics frame); - - /** - * Requests handling of a double tap. |point| is in CSS pixels, relative to - * the scroll offset. This message is expected to round-trip back to - * ZoomToRect() with a rect indicating where we should zoom to. - */ - HandleDoubleTap(nsIntPoint point); + UpdateFrame(nsIntRect displayPort, + nsIntPoint scrollOffset, + gfxSize resolution, + nsIntRect screenSize); /** * Sending an activate message moves focus to the child. @@ -359,4 +342,4 @@ state DYING: }; } -} +} \ No newline at end of file diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index a6e71ee665d8..8aee4abbf25e 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -20,7 +20,6 @@ #include "mozilla/layers/CompositorChild.h" #include "mozilla/layers/PLayersChild.h" #include "mozilla/layout/RenderFrameChild.h" -#include "mozilla/unused.h" #include "nsComponentManagerUtils.h" #include "nsComponentManagerUtils.h" #include "nsContentUtils.h" @@ -107,40 +106,6 @@ TabChild::TabChild(PRUint32 aChromeFlags, bool aIsBrowserElement, printf("creating %d!\n", NS_IsMainThread()); } -nsresult -TabChild::Observe(nsISupports *aSubject, - const char *aTopic, - const PRUnichar *aData) -{ - if (!strcmp(aTopic, "dom-touch-listener-added")) { - nsCOMPtr subject(do_QueryInterface(aSubject)); - nsCOMPtr win(do_GetInterface(mWebNav)); - nsCOMPtr topSubject; - subject->GetTop(getter_AddRefs(topSubject)); - if (win == topSubject) { - SendNotifyDOMTouchListenerAdded(); - } - } else if (!strcmp(aTopic, "cancel-default-pan-zoom")) { - nsCOMPtr docShell(do_QueryInterface(aSubject)); - nsCOMPtr tabChild(GetTabChildFrom(docShell)); - if (tabChild == this) { - mRemoteFrame->CancelDefaultPanZoom(); - } - } else if (!strcmp(aTopic, "browser-zoom-to-rect")) { - nsCOMPtr docShell(do_QueryInterface(aSubject)); - nsCOMPtr tabChild(GetTabChildFrom(docShell)); - if (tabChild == this) { - gfxRect rect; - sscanf(NS_ConvertUTF16toUTF8(aData).get(), - "{\"x\":%lf,\"y\":%lf,\"w\":%lf,\"h\":%lf}", - &rect.x, &rect.y, &rect.width, &rect.height); - SendZoomToRect(rect); - } - } - - return NS_OK; -} - nsresult TabChild::Init() { @@ -156,22 +121,6 @@ TabChild::Init() nsCOMPtr docShellItem(do_QueryInterface(mWebNav)); docShellItem->SetItemType(nsIDocShellTreeItem::typeContentWrapper); - - nsCOMPtr observerService = - do_GetService(NS_OBSERVERSERVICE_CONTRACTID); - - if (observerService) { - observerService->AddObserver(this, - "dom-touch-listener-added", - false); - observerService->AddObserver(this, - "cancel-default-pan-zoom", - false); - observerService->AddObserver(this, - "browser-zoom-to-rect", - false); - } - return NS_OK; } @@ -695,17 +644,41 @@ TabChild::RecvUpdateDimensions(const nsRect& rect, const nsIntSize& size) return true; } -void -TabChild::DispatchMessageManagerMessage(const nsAString& aMessageName, - const nsACString& aJSONData) +bool +TabChild::RecvUpdateFrame(const nsIntRect& aDisplayPort, + const nsIntPoint& aScrollOffset, + const gfxSize& aResolution, + const nsIntRect& aScreenSize) { + if (!mCx || !mTabChildGlobal) { + return true; + } + nsCString data; + data += nsPrintfCString("{ \"x\" : %d", aScrollOffset.x); + data += nsPrintfCString(", \"y\" : %d", aScrollOffset.y); + // We don't treat the x and y scales any differently for this + // semi-platform-specific code. + data += nsPrintfCString(", \"zoom\" : %f", aResolution.width); + data += nsPrintfCString(", \"displayPort\" : "); + data += nsPrintfCString("{ \"left\" : %d", aDisplayPort.X()); + data += nsPrintfCString(", \"top\" : %d", aDisplayPort.Y()); + data += nsPrintfCString(", \"width\" : %d", aDisplayPort.Width()); + data += nsPrintfCString(", \"height\" : %d", aDisplayPort.Height()); + data += nsPrintfCString(", \"resolution\" : %f", aResolution.width); + data += nsPrintfCString(" }"); + data += nsPrintfCString(", \"screenSize\" : "); + data += nsPrintfCString("{ \"width\" : %d", aScreenSize.width); + data += nsPrintfCString(", \"height\" : %d", aScreenSize.height); + data += nsPrintfCString(" }"); + data += nsPrintfCString(" }"); + JSAutoRequest ar(mCx); jsval json = JSVAL_NULL; StructuredCloneData cloneData; JSAutoStructuredCloneBuffer buffer; if (JS_ParseJSON(mCx, - static_cast(NS_ConvertUTF8toUTF16(aJSONData).get()), - aJSONData.Length(), + static_cast(NS_ConvertUTF8toUTF16(data).get()), + data.Length(), &json)) { WriteStructuredClone(mCx, json, buffer, cloneData.mClosure); cloneData.mData = buffer.data(); @@ -718,60 +691,8 @@ TabChild::DispatchMessageManagerMessage(const nsAString& aMessageName, nsRefPtr mm = static_cast(mTabChildGlobal->mMessageManager.get()); mm->ReceiveMessage(static_cast(mTabChildGlobal), - aMessageName, false, &cloneData, nullptr, nullptr); -} - -bool -TabChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics) -{ - if (!mCx || !mTabChildGlobal) { - return true; - } - - nsCString data; - data += nsPrintfCString("{ \"x\" : %d", aFrameMetrics.mViewportScrollOffset.x); - data += nsPrintfCString(", \"y\" : %d", aFrameMetrics.mViewportScrollOffset.y); - // We don't treat the x and y scales any differently for this - // semi-platform-specific code. - data += nsPrintfCString(", \"zoom\" : %f", aFrameMetrics.mResolution.width); - data += nsPrintfCString(", \"displayPort\" : "); - data += nsPrintfCString("{ \"left\" : %d", aFrameMetrics.mDisplayPort.X()); - data += nsPrintfCString(", \"top\" : %d", aFrameMetrics.mDisplayPort.Y()); - data += nsPrintfCString(", \"width\" : %d", aFrameMetrics.mDisplayPort.Width()); - data += nsPrintfCString(", \"height\" : %d", aFrameMetrics.mDisplayPort.Height()); - data += nsPrintfCString(", \"resolution\" : %f", aFrameMetrics.mResolution.width); - data += nsPrintfCString(" }"); - data += nsPrintfCString(", \"screenSize\" : "); - data += nsPrintfCString("{ \"width\" : %d", aFrameMetrics.mViewport.width); - data += nsPrintfCString(", \"height\" : %d", aFrameMetrics.mViewport.height); - data += nsPrintfCString(" }"); - data += nsPrintfCString(", \"cssPageRect\" : "); - data += nsPrintfCString("{ \"x\" : %f", aFrameMetrics.mCSSContentRect.x); - data += nsPrintfCString(", \"y\" : %f", aFrameMetrics.mCSSContentRect.y); - data += nsPrintfCString(", \"width\" : %f", aFrameMetrics.mCSSContentRect.width); - data += nsPrintfCString(", \"height\" : %f", aFrameMetrics.mCSSContentRect.height); - data += nsPrintfCString(" }"); - data += nsPrintfCString(" }"); - - DispatchMessageManagerMessage(NS_LITERAL_STRING("Viewport:Change"), data); - - return true; -} - -bool -TabChild::RecvHandleDoubleTap(const nsIntPoint& aPoint) -{ - if (!mCx || !mTabChildGlobal) { - return true; - } - - nsCString data; - data += nsPrintfCString("{ \"x\" : %d", aPoint.x); - data += nsPrintfCString(", \"y\" : %d", aPoint.y); - data += nsPrintfCString(" }"); - - DispatchMessageManagerMessage(NS_LITERAL_STRING("Gesture:DoubleTap"), data); - + NS_LITERAL_STRING("Viewport:Change"), false, + &cloneData, nullptr, nullptr); return true; } diff --git a/dom/ipc/TabChild.h b/dom/ipc/TabChild.h index 34c540d1fb80..67b6c2ade8aa 100644 --- a/dom/ipc/TabChild.h +++ b/dom/ipc/TabChild.h @@ -47,7 +47,6 @@ #include "nsWeakReference.h" #include "nsITabChild.h" #include "mozilla/Attributes.h" -#include "FrameMetrics.h" struct gfxMatrix; @@ -141,8 +140,7 @@ class TabChild : public PBrowserChild, public nsIWindowProvider, public nsSupportsWeakReference, public nsIDialogCreator, - public nsITabChild, - public nsIObserver + public nsITabChild { typedef mozilla::layout::RenderFrameChild RenderFrameChild; typedef mozilla::dom::ClonedMessageData ClonedMessageData; @@ -168,13 +166,14 @@ public: NS_DECL_NSIWINDOWPROVIDER NS_DECL_NSIDIALOGCREATOR NS_DECL_NSITABCHILD - NS_DECL_NSIOBSERVER virtual bool RecvLoadURL(const nsCString& uri); virtual bool RecvShow(const nsIntSize& size); virtual bool RecvUpdateDimensions(const nsRect& rect, const nsIntSize& size); - virtual bool RecvUpdateFrame(const mozilla::layers::FrameMetrics& aFrameMetrics); - virtual bool RecvHandleDoubleTap(const nsIntPoint& aPoint); + virtual bool RecvUpdateFrame(const nsIntRect& aDisplayPort, + const nsIntPoint& aScrollOffset, + const gfxSize& aResolution, + const nsIntRect& aScreenSize); virtual bool RecvActivate(); virtual bool RecvDeactivate(); virtual bool RecvMouseEvent(const nsString& aType, @@ -288,14 +287,6 @@ private: // Call RecvShow(nsIntSize(0, 0)) and block future calls to RecvShow(). void DoFakeShow(); - // Wraps up a JSON object as a structured clone and sends it to the browser - // chrome script. - // - // XXX/bug 780335: Do the work the browser chrome script does in C++ instead - // so we don't need things like this. - void DispatchMessageManagerMessage(const nsAString& aMessageName, - const nsACString& aJSONData); - nsresult BrowserFrameProvideWindow(nsIDOMWindow* aOpener, nsIURI* aURI, diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index 7ff2a4701ef2..39c34f12d713 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -225,12 +225,10 @@ TabParent::UpdateDimensions(const nsRect& rect, const nsIntSize& size) void TabParent::UpdateFrame(const FrameMetrics& aFrameMetrics) { - unused << SendUpdateFrame(aFrameMetrics); -} - -void TabParent::HandleDoubleTap(const nsIntPoint& aPoint) -{ - unused << SendHandleDoubleTap(aPoint); + unused << SendUpdateFrame(aFrameMetrics.mDisplayPort, + aFrameMetrics.mViewportScrollOffset, + aFrameMetrics.mResolution, + aFrameMetrics.mViewport); } void @@ -1092,23 +1090,5 @@ TabParent::RecvBrowserFrameOpenWindow(PBrowserParent* aOpener, return true; } -bool -TabParent::RecvNotifyDOMTouchListenerAdded() -{ - if (RenderFrameParent* rfp = GetRenderFrame()) { - rfp->NotifyDOMTouchListenerAdded(); - } - return true; -} - -bool -TabParent::RecvZoomToRect(const gfxRect& aRect) -{ - if (RenderFrameParent* rfp = GetRenderFrame()) { - rfp->ZoomToRect(aRect); - } - return true; -} - } // namespace tabs } // namespace mozilla diff --git a/dom/ipc/TabParent.h b/dom/ipc/TabParent.h index a29307b46db8..b3b80598b577 100644 --- a/dom/ipc/TabParent.h +++ b/dom/ipc/TabParent.h @@ -101,8 +101,6 @@ public: virtual bool RecvSetBackgroundColor(const nscolor& aValue); virtual bool RecvGetDPI(float* aValue); virtual bool RecvGetWidgetNativeData(WindowsHandle* aValue); - virtual bool RecvNotifyDOMTouchListenerAdded(); - virtual bool RecvZoomToRect(const gfxRect& aRect); virtual PContentDialogParent* AllocPContentDialog(const PRUint32& aType, const nsCString& aName, const nsCString& aFeatures, @@ -122,7 +120,6 @@ public: void Show(const nsIntSize& size); void UpdateDimensions(const nsRect& rect, const nsIntSize& size); void UpdateFrame(const layers::FrameMetrics& aFrameMetrics); - void HandleDoubleTap(const nsIntPoint& aPoint); void Activate(); void Deactivate(); diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index a2b3a33dda78..7972f567bbff 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -6,26 +6,19 @@ #include "CompositorParent.h" #include "mozilla/gfx/2D.h" -#include "mozilla/ClearOnShutdown.h" #include "mozilla/Constants.h" #include "mozilla/Util.h" #include "mozilla/XPCOM.h" #include "mozilla/Monitor.h" -#include "mozilla/StaticPtr.h" #include "AsyncPanZoomController.h" #include "GestureEventListener.h" #include "nsIThreadManager.h" #include "nsThreadUtils.h" #include "Layers.h" -#include "AnimationCommon.h" - -using namespace mozilla::css; namespace mozilla { namespace layers { -const float AsyncPanZoomController::TOUCH_START_TOLERANCE = 1.0f/16.0f; - static const float EPSILON = 0.0001; /** @@ -51,26 +44,6 @@ static const float MIN_SKATE_SPEED = 0.5f; */ static const float AXIS_LOCK_ANGLE = M_PI / 6.0; -/** - * Duration of a zoom to animation. - */ -static const TimeDuration ZOOM_TO_DURATION = TimeDuration::FromSeconds(0.25); - -/** - * Computed time function used for sampling frames of a zoom to animation. - */ -StaticAutoPtr gComputedTimingFunction; - -/** - * Maximum zoom amount, always used, even if a page asks for higher. - */ -static const double MAX_ZOOM = 8.0; - -/** - * Minimum zoom amount, always used, even if a page asks for lower. - */ -static const double MIN_ZOOM = 0.125; - AsyncPanZoomController::AsyncPanZoomController(GeckoContentController* aGeckoContentController, GestureBehavior aGestures) : mGeckoContentController(aGeckoContentController), @@ -80,22 +53,13 @@ AsyncPanZoomController::AsyncPanZoomController(GeckoContentController* aGeckoCon mLastSampleTime(TimeStamp::Now()), mState(NOTHING), mDPI(72), - mContentPainterStatus(CONTENT_IDLE), - mMayHaveTouchListeners(false), - mDisableNextTouchBatch(false) + mContentPainterStatus(CONTENT_IDLE) { if (aGestures == USE_GESTURE_DETECTOR) { mGestureEventListener = new GestureEventListener(this); } SetDPI(mDPI); - - if (!gComputedTimingFunction) { - gComputedTimingFunction = new ComputedTimingFunction(); - gComputedTimingFunction->Init( - nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE)); - ClearOnShutdown(&gComputedTimingFunction); - } } AsyncPanZoomController::~AsyncPanZoomController() { @@ -182,7 +146,7 @@ AsyncPanZoomController::HandleInputEvent(const nsInputEvent& aEvent, nsEventStatus AsyncPanZoomController::HandleInputEvent(const InputData& aEvent) { nsEventStatus rv = nsEventStatus_eIgnore; - if (mGestureEventListener && !mDisableNextTouchBatch) { + if (mGestureEventListener) { nsEventStatus rv = mGestureEventListener->HandleInputEvent(aEvent); if (rv == nsEventStatus_eConsumeNoDefault) return rv; @@ -236,22 +200,13 @@ nsEventStatus AsyncPanZoomController::OnTouchStart(const MultiTouchInput& aEvent PRInt32 xPos = point.x, yPos = point.y; switch (mState) { - case ANIMATING_ZOOM: - // We just interrupted a double-tap animation, so force a redraw in case - // this touchstart is just a tap that doesn't end up triggering a redraw. - RequestContentRepaint(); - ScheduleComposite(); - // Fall through. case FLING: - { - MonitorAutoLock monitor(mMonitor); - CancelAnimation(); - } + CancelAnimation(); // Fall through. case NOTHING: mX.StartTouch(xPos); mY.StartTouch(yPos); - SetState(TOUCHING); + mState = TOUCHING; break; case TOUCHING: case PANNING: @@ -267,28 +222,20 @@ nsEventStatus AsyncPanZoomController::OnTouchStart(const MultiTouchInput& aEvent } nsEventStatus AsyncPanZoomController::OnTouchMove(const MultiTouchInput& aEvent) { - if (mDisableNextTouchBatch) { - return nsEventStatus_eIgnore; - } - switch (mState) { case FLING: case NOTHING: - case ANIMATING_ZOOM: // May happen if the user double-taps and drags without lifting after the // second tap. Ignore the move if this happens. return nsEventStatus_eIgnore; case TOUCHING: { - float panThreshold = TOUCH_START_TOLERANCE * mDPI; + float panThreshold = 1.0f/2.0f * mDPI; UpdateWithTouchAtDevicePoint(aEvent); - if (PanDistance() < panThreshold) { return nsEventStatus_eIgnore; } - StartPanning(aEvent); - return nsEventStatus_eConsumeNoDefault; } @@ -306,24 +253,18 @@ nsEventStatus AsyncPanZoomController::OnTouchMove(const MultiTouchInput& aEvent) } nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent) { - if (mDisableNextTouchBatch) { - mDisableNextTouchBatch = false; - return nsEventStatus_eIgnore; - } - switch (mState) { case FLING: // Should never happen. NS_WARNING("Received impossible touch end in OnTouchEnd."); // Fall through. - case ANIMATING_ZOOM: case NOTHING: // May happen if the user double-taps and drags without lifting after the // second tap. Ignore if this happens. return nsEventStatus_eIgnore; case TOUCHING: - SetState(NOTHING); + mState = NOTHING; return nsEventStatus_eIgnore; case PANNING: @@ -332,10 +273,10 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent) ScheduleComposite(); RequestContentRepaint(); } - SetState(FLING); + mState = FLING; return nsEventStatus_eConsumeNoDefault; case PINCHING: - SetState(NOTHING); + mState = NOTHING; // Scale gesture listener should have handled this. NS_WARNING("Gesture listener should have handled pinching in OnTouchEnd."); return nsEventStatus_eIgnore; @@ -345,12 +286,12 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent) } nsEventStatus AsyncPanZoomController::OnTouchCancel(const MultiTouchInput& aEvent) { - SetState(NOTHING); + mState = NOTHING; return nsEventStatus_eConsumeNoDefault; } nsEventStatus AsyncPanZoomController::OnScaleBegin(const PinchGestureInput& aEvent) { - SetState(PINCHING); + mState = PINCHING; mLastZoomFocus = aEvent.mFocusPoint; return nsEventStatus_eConsumeNoDefault; @@ -388,14 +329,14 @@ nsEventStatus AsyncPanZoomController::OnScale(const PinchGestureInput& aEvent) { PRInt32 neededDisplacementX = 0, neededDisplacementY = 0; // Only do the scaling if we won't go over 8x zoom in or out. - bool doScale = (scale < MAX_ZOOM && spanRatio > 1.0f) || (scale > MIN_ZOOM && spanRatio < 1.0f); + bool doScale = (scale < 8.0f && spanRatio > 1.0f) || (scale > 0.125f && spanRatio < 1.0f); // If this zoom will take it over 8x zoom in either direction, but it's not // already there, then normalize it. - if (scale * spanRatio > MAX_ZOOM) { - spanRatio = scale / MAX_ZOOM; - } else if (scale * spanRatio < MIN_ZOOM) { - spanRatio = scale / MIN_ZOOM; + if (scale * spanRatio > 8.0f) { + spanRatio = scale / 8.0f; + } else if (scale * spanRatio < 0.125f) { + spanRatio = scale / 0.125f; } if (doScale) { @@ -452,7 +393,7 @@ nsEventStatus AsyncPanZoomController::OnScale(const PinchGestureInput& aEvent) { } nsEventStatus AsyncPanZoomController::OnScaleEnd(const PinchGestureInput& aEvent) { - SetState(PANNING); + mState = PANNING; mX.StartTouch(aEvent.mFocusPoint.x); mY.StartTouch(aEvent.mFocusPoint.y); { @@ -480,15 +421,7 @@ nsEventStatus AsyncPanZoomController::OnSingleTapConfirmed(const TapGestureInput } nsEventStatus AsyncPanZoomController::OnDoubleTap(const TapGestureInput& aEvent) { - if (mGeckoContentController) { - MonitorAutoLock monitor(mMonitor); - - gfx::Point point = WidgetSpaceToCompensatedViewportSpace( - gfx::Point(aEvent.mPoint.x, aEvent.mPoint.y), - mFrameMetrics.mResolution.width); - mGeckoContentController->HandleDoubleTap(nsIntPoint(NS_lround(point.x), NS_lround(point.y))); - return nsEventStatus_eConsumeNoDefault; - } + // XXX: Implement this. return nsEventStatus_eIgnore; } @@ -498,12 +431,14 @@ nsEventStatus AsyncPanZoomController::OnCancelTap(const TapGestureInput& aEvent) } float AsyncPanZoomController::PanDistance() { - MonitorAutoLock monitor(mMonitor); - return NS_hypot(mX.PanDistance(), mY.PanDistance()); + return NS_hypot(mX.PanDistance(), mY.PanDistance()) * mFrameMetrics.mResolution.width; } -const gfx::Point AsyncPanZoomController::GetVelocityVector() { - return gfx::Point(mX.GetVelocity(), mY.GetVelocity()); +const nsPoint AsyncPanZoomController::GetVelocityVector() { + return nsPoint( + mX.GetVelocity(), + mY.GetVelocity() + ); } void AsyncPanZoomController::StartPanning(const MultiTouchInput& aEvent) { @@ -517,7 +452,7 @@ void AsyncPanZoomController::StartPanning(const MultiTouchInput& aEvent) { mX.StartTouch(touch.mScreenPoint.x); mY.StartTouch(touch.mScreenPoint.y); - SetState(PANNING); + mState = PANNING; if (angle < AXIS_LOCK_ANGLE || angle > (M_PI - AXIS_LOCK_ANGLE)) { mY.LockPanning(); @@ -624,7 +559,7 @@ void AsyncPanZoomController::SetPageRect(const gfx::Rect& aCSSPageRect) { float scale = mFrameMetrics.mResolution.width; // The page rect is the css page rect scaled by the current zoom. - pageSize.ScaleRoundOut(1 / scale); + pageSize.ScaleRoundOut(scale); // Round the page rect so we don't get any truncation, then get the nsIntRect // from this. @@ -638,8 +573,7 @@ void AsyncPanZoomController::ScaleWithFocus(float aScale, const nsIntPoint& aFoc FrameMetrics metrics(mFrameMetrics); // Don't set the scale to the inputted value, but rather multiply it in. - float scaleFactor = aScale / metrics.mResolution.width, - oldScale = metrics.mResolution.width; + float scaleFactor = aScale / metrics.mResolution.width; metrics.mResolution.width = metrics.mResolution.height = aScale; @@ -649,38 +583,21 @@ void AsyncPanZoomController::ScaleWithFocus(float aScale, const nsIntPoint& aFoc nsIntPoint scrollOffset = metrics.mViewportScrollOffset; - scrollOffset.x += NS_lround(float(aFocus.x) * (scaleFactor - 1.0f) / oldScale); - scrollOffset.y += NS_lround(float(aFocus.y) * (scaleFactor - 1.0f) / oldScale); + scrollOffset.x += aFocus.x * (scaleFactor - 1.0f); + scrollOffset.y += aFocus.y * (scaleFactor - 1.0f); metrics.mViewportScrollOffset = scrollOffset; mFrameMetrics = metrics; } -bool AsyncPanZoomController::EnlargeDisplayPortAlongAxis(float aViewport, - float aVelocity, - float* aDisplayPortOffset, - float* aDisplayPortLength) -{ - const float MIN_SKATE_SIZE_MULTIPLIER = 2.0f; - const float MAX_SKATE_SIZE_MULTIPLIER = 4.0f; - - if (fabsf(aVelocity) > MIN_SKATE_SPEED) { - *aDisplayPortLength = aViewport * clamped(fabsf(aVelocity), - MIN_SKATE_SIZE_MULTIPLIER, MAX_SKATE_SIZE_MULTIPLIER); - *aDisplayPortOffset = aVelocity > 0 ? 0 : aViewport - *aDisplayPortLength; - return true; - } - return false; -} - const nsIntRect AsyncPanZoomController::CalculatePendingDisplayPort() { float scale = mFrameMetrics.mResolution.width; nsIntRect viewport = mFrameMetrics.mViewport; viewport.ScaleRoundIn(1 / scale); nsIntPoint scrollOffset = mFrameMetrics.mViewportScrollOffset; - gfx::Point velocity = GetVelocityVector(); + nsPoint velocity = GetVelocityVector(); // The displayport is relative to the current scroll offset. Here's a little // diagram to make it easier to see: @@ -707,25 +624,28 @@ const nsIntRect AsyncPanZoomController::CalculatePendingDisplayPort() { // and far top, it is clear that this distance is 1/4 of the displayport's // height/width dimension. const float STATIONARY_SIZE_MULTIPLIER = 2.0f; + const float SKATE_SIZE_MULTIPLIER = 3.0f; gfx::Rect displayPort(0, 0, viewport.width * STATIONARY_SIZE_MULTIPLIER, viewport.height * STATIONARY_SIZE_MULTIPLIER); - // If there's motion along an axis of movement, and it's above a threshold, - // then we want to paint a larger area in the direction of that motion so that - // it's less likely to checkerboard. - bool enlargedX = EnlargeDisplayPortAlongAxis( - viewport.width, velocity.x, &displayPort.x, &displayPort.width); - bool enlargedY = EnlargeDisplayPortAlongAxis( - viewport.height, velocity.y, &displayPort.y, &displayPort.height); - - if (!enlargedX && !enlargedY) { + // Iff there's motion along only one axis of movement, and it's above a + // threshold, then we want to paint a larger area in the direction of that + // motion so that it's less likely to checkerboard. Also note that the other + // axis doesn't need its displayport enlarged beyond the viewport dimension, + // since it is impossible for it to checkerboard along that axis until motion + // begins on it. + if (fabsf(velocity.x) > MIN_SKATE_SPEED && fabsf(velocity.y) < MIN_SKATE_SPEED) { + displayPort.height = viewport.height; + displayPort.width = viewport.width * SKATE_SIZE_MULTIPLIER; + displayPort.x = velocity.x > 0 ? 0 : viewport.width - displayPort.width; + } else if (fabsf(velocity.x) < MIN_SKATE_SPEED && fabsf(velocity.y) > MIN_SKATE_SPEED) { + displayPort.width = viewport.width; + displayPort.height = viewport.height * SKATE_SIZE_MULTIPLIER; + displayPort.y = velocity.y > 0 ? 0 : viewport.height - displayPort.height; + } else { displayPort.x = -displayPort.width / 4; displayPort.y = -displayPort.height / 4; - } else if (!enlargedX) { - displayPort.width = viewport.width; - } else if (!enlargedY) { - displayPort.height = viewport.height; } gfx::Rect shiftedDisplayPort = displayPort; @@ -743,10 +663,6 @@ void AsyncPanZoomController::SetDPI(int aDPI) { mDPI = aDPI; } -int AsyncPanZoomController::GetDPI() { - return mDPI; -} - void AsyncPanZoomController::ScheduleComposite() { if (mCompositorParent) { mCompositorParent->ScheduleRenderOnCompositorThread(); @@ -800,43 +716,9 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa { MonitorAutoLock mon(mMonitor); - switch (mState) - { - case FLING: - // If a fling is currently happening, apply it now. We can pull the updated - // metrics afterwards. - requestAnimationFrame |= DoFling(aSampleTime - mLastSampleTime); - break; - case ANIMATING_ZOOM: { - double animPosition = (aSampleTime - mAnimationStartTime) / ZOOM_TO_DURATION; - if (animPosition > 1.0) { - animPosition = 1.0; - } - double sampledPosition = gComputedTimingFunction->GetValue(animPosition); - - mFrameMetrics.mResolution.width = mFrameMetrics.mResolution.height = - mEndZoomToMetrics.mResolution.width * sampledPosition + - mStartZoomToMetrics.mResolution.width * (1 - sampledPosition); - - mFrameMetrics.mViewportScrollOffset = nsIntPoint( - mEndZoomToMetrics.mViewportScrollOffset.x * sampledPosition + - mStartZoomToMetrics.mViewportScrollOffset.x * (1 - sampledPosition), - mEndZoomToMetrics.mViewportScrollOffset.y * sampledPosition + - mStartZoomToMetrics.mViewportScrollOffset.y * (1 - sampledPosition) - ); - - requestAnimationFrame = true; - - if (aSampleTime - mAnimationStartTime >= ZOOM_TO_DURATION) { - mState = NOTHING; - RequestContentRepaint(); - } - - break; - } - default: - break; - } + // If a fling is currently happening, apply it now. We can pull the updated + // metrics afterwards. + requestAnimationFrame = requestAnimationFrame || DoFling(aSampleTime - mLastSampleTime); // Current local transform; this is not what's painted but rather what PZC has // transformed due to touches like panning or pinching. Eventually, the root @@ -902,11 +784,7 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aViewportFr // we get a larger displayport. This is very bad because we're wasting a // paint and not initializating the displayport correctly. RequestContentRepaint(); - - // Assuming a first paint means a new page has been loaded, clear the flag - // indicating that we may have touch listeners. - mMayHaveTouchListeners = false; - } else if (!mFrameMetrics.mCSSContentRect.IsEqualEdges(aViewportFrame.mCSSContentRect)) { + } else if (!mFrameMetrics.mContentRect.IsEqualEdges(aViewportFrame.mContentRect)) { mFrameMetrics.mCSSContentRect = aViewportFrame.mCSSContentRect; SetPageRect(mFrameMetrics.mCSSContentRect); } @@ -924,95 +802,5 @@ void AsyncPanZoomController::UpdateViewportSize(int aWidth, int aHeight) { mFrameMetrics = metrics; } -void AsyncPanZoomController::NotifyDOMTouchListenerAdded() { - mMayHaveTouchListeners = true; -} - -void AsyncPanZoomController::CancelDefaultPanZoom() { - mDisableNextTouchBatch = true; - if (mGestureEventListener) { - mGestureEventListener->CancelGesture(); - } -} - -void AsyncPanZoomController::ZoomToRect(const gfxRect& aRect) { - gfx::Rect zoomToRect(gfx::Rect(aRect.x, aRect.y, aRect.width, aRect.height)); - gfx::Rect cssPageRect = mFrameMetrics.mCSSContentRect; - - SetState(ANIMATING_ZOOM); - - { - MonitorAutoLock mon(mMonitor); - - nsIntRect viewport = mFrameMetrics.mViewport; - - // If the rect is empty, treat it as a request to zoom out to the full page - // size. - if (zoomToRect.IsEmpty()) { - nsIntRect cssViewport = viewport; - cssViewport.ScaleRoundIn(1 / mFrameMetrics.mResolution.width); - cssViewport.MoveBy(mFrameMetrics.mViewportScrollOffset); - - float y = mFrameMetrics.mViewportScrollOffset.y; - float newHeight = cssViewport.height * cssPageRect.width / cssViewport.width; - float dh = cssViewport.height - newHeight; - - zoomToRect = gfx::Rect(0.0f, - y + dh/2, - cssPageRect.width, - y + dh/2 + newHeight); - } else { - float targetRatio = float(viewport.width) / float(viewport.height); - float rectRatio = zoomToRect.width / zoomToRect.height; - - if (fabsf(targetRatio - rectRatio) < EPSILON) { - // All good, do nothing. - } else if (targetRatio < rectRatio) { - // Need to increase zoomToRect height. - float newHeight = zoomToRect.height / targetRatio; - zoomToRect.y -= (newHeight - zoomToRect.height) / 2; - zoomToRect.height = newHeight; - } else { // (targetRatio > rectRatio) { - // Need to increase zoomToRect width. - float newWidth = targetRatio * zoomToRect.width; - zoomToRect.x -= (newWidth - zoomToRect.width) / 2; - zoomToRect.width = newWidth; - } - - zoomToRect = zoomToRect.Intersect(cssPageRect); - } - - mEndZoomToMetrics.mResolution.width = mEndZoomToMetrics.mResolution.height = - NS_MIN(viewport.width / zoomToRect.width, viewport.height / zoomToRect.height); - - mEndZoomToMetrics.mResolution.width = mEndZoomToMetrics.mResolution.height = - clamped(mEndZoomToMetrics.mResolution.width, MIN_ZOOM, MAX_ZOOM); - - // Recalculate the zoom to rect using the new dimensions. - zoomToRect.width = viewport.width / mEndZoomToMetrics.mResolution.width; - zoomToRect.height = viewport.height / mEndZoomToMetrics.mResolution.height; - - // Clamp the zoom to rect to the CSS rect to make sure it fits. - zoomToRect = zoomToRect.Intersect(cssPageRect); - - // Do one final recalculation to get the resolution. - mEndZoomToMetrics.mResolution.width = mEndZoomToMetrics.mResolution.height = - NS_MAX(viewport.width / zoomToRect.width, viewport.height / zoomToRect.height); - - mStartZoomToMetrics = mFrameMetrics; - mEndZoomToMetrics.mViewportScrollOffset = - nsIntPoint(NS_lround(zoomToRect.x), NS_lround(zoomToRect.y)); - - mAnimationStartTime = TimeStamp::Now(); - - ScheduleComposite(); - } -} - -void AsyncPanZoomController::SetState(PanZoomState aState) { - MonitorAutoLock monitor(mMonitor); - mState = aState; -} - } } diff --git a/gfx/layers/ipc/AsyncPanZoomController.h b/gfx/layers/ipc/AsyncPanZoomController.h index ac825bf46fa7..2322b06e5037 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.h +++ b/gfx/layers/ipc/AsyncPanZoomController.h @@ -57,14 +57,6 @@ public: USE_GESTURE_DETECTOR }; - /** - * Constant describing the tolerance in distance we use, multiplied by the - * device DPI, before we start panning the screen. This is to prevent us from - * accidentally processing taps as touch moves, and from very short/accidental - * touches moving the screen. - */ - static const float TOUCH_START_TOLERANCE; - AsyncPanZoomController(GeckoContentController* aController, GestureBehavior aGestures = DEFAULT_GESTURES); ~AsyncPanZoomController(); @@ -107,33 +99,6 @@ public: */ void UpdateViewportSize(int aWidth, int aHeight); - /** - * A DOM touch listener has been added. When called, we enable the machinery - * that allows touch listeners to preventDefault any touch inputs. This should - * not be called unless there are actually touch listeners as it introduces - * potentially unbounded lag because it causes a round-trip through content. - * Usually, if content is responding in a timely fashion, this only introduces - * a nearly constant few hundred ms of lag. - */ - void NotifyDOMTouchListenerAdded(); - - /** - * We have found a scrollable subframe, so disable our machinery until we hit - * a touch end or a new touch start. This prevents us from accidentally - * panning both the subframe and the parent frame. - * - * XXX/bug 775452: We should eventually be supporting async scrollable - * subframes. - */ - void CancelDefaultPanZoom(); - - /** - * Kicks an animation to zoom to a rect. This may be either a zoom out or zoom - * in. The actual animation is done on the compositor thread after being set - * up. |aRect| must be given in CSS pixels, relative to the document. - */ - void ZoomToRect(const gfxRect& aRect); - // -------------------------------------------------------------------------- // These methods must only be called on the compositor thread. // @@ -187,12 +152,6 @@ public: */ void SetDPI(int aDPI); - /** - * Gets the DPI of the device for use outside the panning and zooming logic. - * It defaults to 72 if not set using SetDPI() at any point. - */ - int GetDPI(); - protected: /** * Helper method for touches beginning. Sets everything up for panning and any @@ -296,8 +255,6 @@ protected: * Cancels any currently running animation. Note that all this does is set the * state of the AsyncPanZoomController back to NOTHING, but it is the * animation's responsibility to check this before advancing. - * - * *** The monitor must be held while calling this. */ void CancelAnimation(); @@ -312,7 +269,7 @@ protected: /** * Gets a vector of the velocities of each axis. */ - const gfx::Point GetVelocityVector(); + const nsPoint GetVelocityVector(); /** * Gets a reference to the first SingleTouchData from a MultiTouchInput. This @@ -347,17 +304,6 @@ protected: */ const nsIntRect CalculatePendingDisplayPort(); - /** - * Attempts to enlarge the displayport along a single axis. Returns whether or - * not the displayport was enlarged. This will fail in circumstances where the - * velocity along that axis is not high enough to need any changes. The - * displayport metrics are expected to be passed into |aDisplayPortOffset| and - * |aDisplayPortLength|. If enlarged, these will be updated with the new - * metrics. - */ - bool EnlargeDisplayPortAlongAxis(float aViewport, float aVelocity, - float* aDisplayPortOffset, float* aDisplayPortLength); - /** * Utility function to send updated FrameMetrics to Gecko so that it can paint * the displayport area. Calls into GeckoContentController to do the actual @@ -389,7 +335,6 @@ private: TOUCHING, /* one touch-start event received */ PANNING, /* panning without axis lock */ PINCHING, /* nth touch-start, where n > 1. this mode allows pan and zoom */ - ANIMATING_ZOOM /* animated zoom to a new rect */ }; enum ContentPainterStatus { @@ -411,13 +356,6 @@ private: CONTENT_PAINTING_AND_PAINT_PENDING }; - /** - * Helper to set the current state. Holds the monitor before actually setting - * it. If the monitor is already held by the current thread, it is safe to - * instead use: |mState = NEWSTATE;| - */ - void SetState(PanZoomState aState); - nsRefPtr mCompositorParent; nsRefPtr mGeckoContentController; nsRefPtr mGestureEventListener; @@ -425,33 +363,17 @@ private: // Both |mFrameMetrics| and |mLastContentPaintMetrics| are protected by the // monitor. Do not read from or modify either of them without locking. FrameMetrics mFrameMetrics; - // These are the metrics at last content paint, the most recent // values we were notified of in NotifyLayersUpdate(). FrameMetrics mLastContentPaintMetrics; - // The last metrics that we requested a paint for. These are used to make sure // that we're not requesting a paint of the same thing that's already drawn. // If we don't do this check, we don't get a ShadowLayersUpdated back. FrameMetrics mLastPaintRequestMetrics; - // Old metrics from before we started a zoom animation. This is only valid - // when we are in the "ANIMATED_ZOOM" state. This is used so that we can - // interpolate between the start and end frames. We only use the - // |mViewportScrollOffset| and |mResolution| fields on this. - FrameMetrics mStartZoomToMetrics; - // Target metrics for a zoom to animation. This is only valid when we are in - // the "ANIMATED_ZOOM" state. We only use the |mViewportScrollOffset| and - // |mResolution| fields on this. - FrameMetrics mEndZoomToMetrics; - AxisX mX; AxisY mY; - // Protects |mFrameMetrics|, |mLastContentPaintMetrics| and |mState|. Before - // manipulating |mFrameMetrics| or |mLastContentPaintMetrics|, the monitor - // should be held. When setting |mState|, either the SetState() function can - // be used, or the monitor can be held and then |mState| updated. Monitor mMonitor; // The last time the compositor has sampled the content transform for this @@ -460,18 +382,10 @@ private: // The last time a touch event came through on the UI thread. PRInt32 mLastEventTime; - // Start time of an animation. This is used for a zoom to animation to mark - // the beginning. - TimeStamp mAnimationStartTime; - // Stores the previous focus point if there is a pinch gesture happening. Used // to allow panning by moving multiple fingers (thus moving the focus point). nsIntPoint mLastZoomFocus; - - // Stores the state of panning and zooming this frame. This is protected by - // |mMonitor|; that is, it should be held whenever this is updated. PanZoomState mState; - int mDPI; // Stores the current paint status of the frame that we're managing. Repaints @@ -480,14 +394,6 @@ private: // requests a repaint. ContentPainterStatus mContentPainterStatus; - // Whether or not we might have touch listeners. This is a conservative - // approximation and may not be accurate. - bool mMayHaveTouchListeners; - - // Flag used to determine whether or not we should disable handling of the - // next batch of touch events. This is used for sync scrolling of subframes. - bool mDisableNextTouchBatch; - friend class Axis; }; diff --git a/gfx/layers/ipc/GeckoContentController.h b/gfx/layers/ipc/GeckoContentController.h index 66a7b5762b64..5c520a2564a0 100644 --- a/gfx/layers/ipc/GeckoContentController.h +++ b/gfx/layers/ipc/GeckoContentController.h @@ -23,14 +23,6 @@ public: */ virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics) = 0; - /** - * Requests handling of a double tap. |aPoint| is in CSS pixels, relative to - * the current scroll offset. This should eventually round-trip back to - * AsyncPanZoomController::ZoomToRect with the dimensions that we want to zoom - * to. - */ - virtual void HandleDoubleTap(const nsIntPoint& aPoint) = 0; - GeckoContentController() {} virtual ~GeckoContentController() {} }; diff --git a/gfx/layers/ipc/GestureEventListener.cpp b/gfx/layers/ipc/GestureEventListener.cpp index 3bc50b1f51e8..e5f1f40ce261 100644 --- a/gfx/layers/ipc/GestureEventListener.cpp +++ b/gfx/layers/ipc/GestureEventListener.cpp @@ -63,7 +63,6 @@ nsEventStatus GestureEventListener::HandleInputEvent(const InputData& aEvent) size_t length = mTouches.Length(); if (length == 1) { mTapStartTime = event.mTime; - mTouchStartPosition = event.mTouches[0].mScreenPoint; if (mState == GESTURE_NONE) { mState = GESTURE_WAITING_SINGLE_TAP; } @@ -75,14 +74,9 @@ nsEventStatus GestureEventListener::HandleInputEvent(const InputData& aEvent) break; } case MultiTouchInput::MULTITOUCH_MOVE: { - // If we move too much, bail out of the tap. - nsIntPoint touch = (nsIntPoint&)event.mTouches[0].mScreenPoint; - if (mTouches.Length() == 1 && - NS_hypot(mTouchStartPosition.x - touch.x, mTouchStartPosition.y - touch.y) > - mAsyncPanZoomController->GetDPI() * AsyncPanZoomController::TOUCH_START_TOLERANCE) - { - HandleTapCancel(event); - } + // If we move at all, just bail out of the tap. We need to change this so + // that there's some tolerance in the future. + HandleTapCancel(event); bool foundAlreadyExistingTouch = false; for (size_t i = 0; i < mTouches.Length(); i++) { @@ -266,10 +260,5 @@ AsyncPanZoomController* GestureEventListener::GetAsyncPanZoomController() { return mAsyncPanZoomController; } -void GestureEventListener::CancelGesture() { - mTouches.Clear(); - mState = GESTURE_NONE; -} - } } diff --git a/gfx/layers/ipc/GestureEventListener.h b/gfx/layers/ipc/GestureEventListener.h index f1fced0f046d..4a227a4f2768 100644 --- a/gfx/layers/ipc/GestureEventListener.h +++ b/gfx/layers/ipc/GestureEventListener.h @@ -1,4 +1,7 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set sw=4 ts=8 et tw=80 : */ /* 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 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=4 ts=8 et tw=80 : */ +/* 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/. */ #ifndef mozilla_layers_GestureEventListener_h @@ -44,13 +47,6 @@ public: */ nsEventStatus HandleInputEvent(const InputData& aEvent); - /** - * Cancels any currently active gesture. May not properly handle situations - * that require extra work at the gesture's end, like a pinch which only - * requests a repaint once it has ended. - */ - void CancelGesture(); - /** * Returns the AsyncPanZoomController stored on this class and used for * callbacks. @@ -167,13 +163,6 @@ protected: * we can cancel it if a double tap actually comes in. */ CancelableTask *mDoubleTapTimeoutTask; - - /** - * Position of the last touch starting. This is only valid during an attempt - * to determine if a touch is a tap. This means that it is used in both the - * "GESTURE_WAITING_SINGLE_TAP" and "GESTURE_WAITING_DOUBLE_TAP" states. - */ - nsIntPoint mTouchStartPosition; }; } diff --git a/ipc/glue/IPCMessageUtils.h b/ipc/glue/IPCMessageUtils.h index c13e27880baa..f86fee9d05a3 100644 --- a/ipc/glue/IPCMessageUtils.h +++ b/ipc/glue/IPCMessageUtils.h @@ -23,13 +23,11 @@ #include "gfxMatrix.h" #include "gfxPattern.h" #include "gfxPoint.h" -#include "gfxRect.h" #include "nsRect.h" #include "nsRegion.h" #include "gfxASurface.h" #include "jsapi.h" #include "LayersTypes.h" -#include "FrameMetrics.h" #ifdef _MSC_VER #pragma warning( disable : 4800 ) @@ -519,28 +517,6 @@ struct ParamTraits } }; -template<> -struct ParamTraits -{ - typedef gfxRect paramType; - - static void Write(Message* aMsg, const paramType& aParam) - { - WriteParam(aMsg, aParam.x); - WriteParam(aMsg, aParam.y); - WriteParam(aMsg, aParam.width); - WriteParam(aMsg, aParam.height); - } - - static bool Read(const Message* aMsg, void** aIter, paramType* aResult) - { - return ReadParam(aMsg, aIter, &aResult->x) && - ReadParam(aMsg, aIter, &aResult->y) && - ReadParam(aMsg, aIter, &aResult->width) && - ReadParam(aMsg, aIter, &aResult->height); - } -}; - template<> struct ParamTraits { diff --git a/layout/ipc/PRenderFrame.ipdl b/layout/ipc/PRenderFrame.ipdl index 0a30fc838748..d84180699647 100644 --- a/layout/ipc/PRenderFrame.ipdl +++ b/layout/ipc/PRenderFrame.ipdl @@ -41,8 +41,6 @@ parent: async NotifyCompositorTransaction(); - async CancelDefaultPanZoom(); - async __delete__(); state EMPTY_OR_DIRECT_COMPOSITOR: diff --git a/layout/ipc/RenderFrameChild.cpp b/layout/ipc/RenderFrameChild.cpp index a2af75b60272..9c3c6fe3fe22 100644 --- a/layout/ipc/RenderFrameChild.cpp +++ b/layout/ipc/RenderFrameChild.cpp @@ -32,12 +32,6 @@ RenderFrameChild::Destroy() // WARNING: |this| is dead, hands off } -void -RenderFrameChild::CancelDefaultPanZoom() -{ - SendCancelDefaultPanZoom(); -} - PLayersChild* RenderFrameChild::AllocPLayers() { diff --git a/layout/ipc/RenderFrameChild.h b/layout/ipc/RenderFrameChild.h index 44f38b175fa5..c9d6fc599604 100644 --- a/layout/ipc/RenderFrameChild.h +++ b/layout/ipc/RenderFrameChild.h @@ -19,8 +19,6 @@ public: RenderFrameChild() {} virtual ~RenderFrameChild() {} - void CancelDefaultPanZoom(); - void Destroy(); protected: diff --git a/layout/ipc/RenderFrameParent.cpp b/layout/ipc/RenderFrameParent.cpp index 34ba23b8372d..896b11d9aac3 100644 --- a/layout/ipc/RenderFrameParent.cpp +++ b/layout/ipc/RenderFrameParent.cpp @@ -492,23 +492,6 @@ public: } } - virtual void HandleDoubleTap(const nsIntPoint& aPoint) MOZ_OVERRIDE - { - if (MessageLoop::current() != mUILoop) { - // We have to send this message from the "UI thread" (main - // thread). - mUILoop->PostTask( - FROM_HERE, - NewRunnableMethod(this, &RemoteContentController::HandleDoubleTap, - aPoint)); - return; - } - if (mRenderFrame) { - TabParent* browser = static_cast(mRenderFrame->Manager()); - browser->HandleDoubleTap(aPoint); - } - } - void ClearRenderFrame() { mRenderFrame = nullptr; } private: @@ -737,15 +720,6 @@ RenderFrameParent::RecvNotifyCompositorTransaction() return true; } -bool -RenderFrameParent::RecvCancelDefaultPanZoom() -{ - if (mPanZoomController) { - mPanZoomController->CancelDefaultPanZoom(); - } - return true; -} - PLayersParent* RenderFrameParent::AllocPLayers() { @@ -878,22 +852,6 @@ RenderFrameParent::BuildDisplayList(nsDisplayListBuilder* aBuilder, bounds)); } -void -RenderFrameParent::NotifyDOMTouchListenerAdded() -{ - if (mPanZoomController) { - mPanZoomController->NotifyDOMTouchListenerAdded(); - } -} - -void -RenderFrameParent::ZoomToRect(const gfxRect& aRect) -{ - if (mPanZoomController) { - mPanZoomController->ZoomToRect(aRect); - } -} - } // namespace layout } // namespace mozilla diff --git a/layout/ipc/RenderFrameParent.h b/layout/ipc/RenderFrameParent.h index 36993e5d08fa..a7ea91feb97a 100644 --- a/layout/ipc/RenderFrameParent.h +++ b/layout/ipc/RenderFrameParent.h @@ -93,17 +93,11 @@ public: void NotifyDimensionsChanged(int width, int height); - void NotifyDOMTouchListenerAdded(); - - void ZoomToRect(const gfxRect& aRect); - protected: void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE; virtual bool RecvNotifyCompositorTransaction() MOZ_OVERRIDE; - virtual bool RecvCancelDefaultPanZoom() MOZ_OVERRIDE; - virtual PLayersParent* AllocPLayers() MOZ_OVERRIDE; virtual bool DeallocPLayers(PLayersParent* aLayers) MOZ_OVERRIDE; From a769fb1ee219c4080e4c46580b188632326b4f51 Mon Sep 17 00:00:00 2001 From: Paul Adenot Date: Tue, 7 Aug 2012 15:54:30 -0700 Subject: [PATCH 110/169] Bug 567077 - Sniff types of media files that are served with no Content-Type r=cpearce --- .../html/content/src/nsHTMLMediaElement.cpp | 3 +- content/media/test/Makefile.in | 4 +- netwerk/mime/nsMimeTypes.h | 1 + toolkit/components/Makefile.in | 1 + toolkit/components/mediasniffer/Makefile.in | 30 +++++ .../mediasniffer/nsMediaSniffer.cpp | 107 ++++++++++++++++++ .../components/mediasniffer/nsMediaSniffer.h | 41 +++++++ .../mediasniffer/nsMediaSnifferModule.cpp | 37 ++++++ toolkit/library/Makefile.in | 1 + toolkit/library/nsStaticXULComponents.cpp | 1 + 10 files changed, 224 insertions(+), 2 deletions(-) create mode 100644 toolkit/components/mediasniffer/Makefile.in create mode 100644 toolkit/components/mediasniffer/nsMediaSniffer.cpp create mode 100644 toolkit/components/mediasniffer/nsMediaSniffer.h create mode 100644 toolkit/components/mediasniffer/nsMediaSnifferModule.cpp diff --git a/content/html/content/src/nsHTMLMediaElement.cpp b/content/html/content/src/nsHTMLMediaElement.cpp index 00efb17b87ac..15635ea983e3 100644 --- a/content/html/content/src/nsHTMLMediaElement.cpp +++ b/content/html/content/src/nsHTMLMediaElement.cpp @@ -1079,7 +1079,8 @@ nsresult nsHTMLMediaElement::LoadResource() nullptr, loadGroup, nullptr, - nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY, + nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY | + nsIChannel::LOAD_TREAT_APPLICATION_OCTET_STREAM_AS_UNKNOWN, channelPolicy); NS_ENSURE_SUCCESS(rv,rv); diff --git a/content/media/test/Makefile.in b/content/media/test/Makefile.in index 5a8df18587d0..d0f1727f33e1 100644 --- a/content/media/test/Makefile.in +++ b/content/media/test/Makefile.in @@ -108,7 +108,7 @@ MOCHITEST_FILES = \ test_seek2.html \ test_source.html \ test_source_write.html \ - test_source_null.html \ + test_source_null.html \ test_standalone.html \ test_streams_element_capture.html \ test_streams_element_capture_reset.html \ @@ -127,6 +127,8 @@ MOCHITEST_FILES = \ test_media_selection.html \ test_playback.html \ test_seekLies.html \ + test_media_sniffer.html \ + contentType.sjs \ $(NULL) # Tests disabled on Linux for frequent intermittent failures diff --git a/netwerk/mime/nsMimeTypes.h b/netwerk/mime/nsMimeTypes.h index b09ce10fdc19..05f9c08d2244 100644 --- a/netwerk/mime/nsMimeTypes.h +++ b/netwerk/mime/nsMimeTypes.h @@ -75,6 +75,7 @@ #define AUDIO_OGG "audio/ogg" #define AUDIO_WAV "audio/x-wav" #define AUDIO_WEBM "audio/webm" +#define AUDIO_MP3 "audio/mpeg" #define BINARY_OCTET_STREAM "binary/octet-stream" diff --git a/toolkit/components/Makefile.in b/toolkit/components/Makefile.in index 3e823257ee3c..95533a69bc5c 100644 --- a/toolkit/components/Makefile.in +++ b/toolkit/components/Makefile.in @@ -27,6 +27,7 @@ PARALLEL_DIRS += \ filepicker \ find \ intl \ + mediasniffer \ microformats \ osfile \ parentalcontrols \ diff --git a/toolkit/components/mediasniffer/Makefile.in b/toolkit/components/mediasniffer/Makefile.in new file mode 100644 index 000000000000..738ba006da8c --- /dev/null +++ b/toolkit/components/mediasniffer/Makefile.in @@ -0,0 +1,30 @@ +# 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/. + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = mediasniffer +LIBRARY_NAME = mediasniffer +LIBXUL_LIBRARY = 1 +EXPORT_LIBRARY = 1 +MODULE_NAME = nsMediaSnifferModule +IS_COMPONENT = 1 + + +CPPSRCS = \ + nsMediaSniffer.cpp \ + nsMediaSnifferModule.cpp \ + $(NULL) + +EXPORTS = \ + nsMediaSniffer.h \ + $(NULL) + +include $(topsrcdir)/config/config.mk +include $(topsrcdir)/config/rules.mk diff --git a/toolkit/components/mediasniffer/nsMediaSniffer.cpp b/toolkit/components/mediasniffer/nsMediaSniffer.cpp new file mode 100644 index 000000000000..7b8c177760ed --- /dev/null +++ b/toolkit/components/mediasniffer/nsMediaSniffer.cpp @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 tw=80 et cindent: */ +/* 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/. */ + +#include "nsMediaSniffer.h" +#include "nsMemory.h" +#include "nsIHttpChannel.h" +#include "nsAString.h" +#include "nsMimeTypes.h" +#include "mozilla/ModuleUtils.h" + +#include "nsIClassInfoImpl.h" + +// The minimum number of bytes that are needed to attempt to sniff an mp4 file. +static const unsigned MP4_MIN_BYTES_COUNT = 12; +// The maximum number of bytes to consider when attempting to sniff a file. +static const PRUint32 MAX_BYTES_SNIFFED = 512; + +NS_IMPL_CLASSINFO(nsMediaSniffer, NULL, 0, NS_MEDIA_SNIFFER_CID) +NS_IMPL_ISUPPORTS1(nsMediaSniffer, nsIContentSniffer) + +nsMediaSniffer::nsMediaSnifferEntry nsMediaSniffer::sSnifferEntries[] = { + // The string OggS, followed by the null byte. + PATTERN_ENTRY("\xFF\xFF\xFF\xFF\xFF", "OggS", APPLICATION_OGG), + // The string RIFF, followed by four bytes, followed by the string WAVE + PATTERN_ENTRY("\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF", "RIFF\x00\x00\x00\x00WAVE", AUDIO_WAV), + // WebM + PATTERN_ENTRY("\xFF\xFF\xFF\xFF", "\x1A\x45\xDF\xA3", VIDEO_WEBM), + // mp3 without ID3 tags. + PATTERN_ENTRY("\xFF\xFB", "\xFF\xFA", AUDIO_MP3), + // mp3 with ID3 tags, the string "ID3". + PATTERN_ENTRY("\xFF\xFF\xFF", "ID3", AUDIO_MP3) +}; + +// This function implements mp4 sniffing algorithm, described at +// http://mimesniff.spec.whatwg.org/#signature-for-mp4 +static bool MatchesMP4(const PRUint8* aData, const PRUint32 aLength) +{ + if (aLength <= MP4_MIN_BYTES_COUNT) { + return false; + } + // Conversion from big endian to host byte order. + PRUint32 boxSize = (PRUint32)(aData[3] | aData[2] << 8 | aData[1] << 16 | aData[0] << 24); + + // Boxsize should be evenly divisible by 4. + if (boxSize % 4 || aLength < boxSize) { + return false; + } + // The string "ftyp". + if (aData[4] != 0x66 || + aData[5] != 0x74 || + aData[6] != 0x79 || + aData[7] != 0x70) { + return false; + } + for (PRUint32 i = 2; i <= boxSize / 4 - 1 ; i++) { + if (i == 3) { + continue; + } + // The string "mp4". + if (aData[4*i] == 0x6D && + aData[4*i+1] == 0x70 && + aData[4*i+2] == 0x34) { + return true; + } + } + return false; +} + +NS_IMETHODIMP +nsMediaSniffer::GetMIMETypeFromContent(nsIRequest* aRequest, + const PRUint8* aData, + const PRUint32 aLength, + nsACString& aSniffedType) +{ + const PRUint32 clampedLength = NS_MIN(aLength, MAX_BYTES_SNIFFED); + + for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(sSnifferEntries); ++i) { + const nsMediaSnifferEntry& currentEntry = sSnifferEntries[i]; + if (clampedLength < currentEntry.mLength || currentEntry.mLength == 0) { + continue; + } + bool matched = true; + for (PRUint32 j = 0; j < currentEntry.mLength; ++j) { + if ((currentEntry.mMask[j] & aData[j]) != currentEntry.mPattern[j]) { + matched = false; + break; + } + } + if (matched) { + aSniffedType.AssignASCII(currentEntry.mContentType); + return NS_OK; + } + } + + if (MatchesMP4(aData, clampedLength)) { + aSniffedType.AssignLiteral(VIDEO_MP4); + return NS_OK; + } + + // Could not sniff the media type, we are required to set it to + // application/octet-stream. + aSniffedType.AssignLiteral(APPLICATION_OCTET_STREAM); + return NS_ERROR_NOT_AVAILABLE; +} diff --git a/toolkit/components/mediasniffer/nsMediaSniffer.h b/toolkit/components/mediasniffer/nsMediaSniffer.h new file mode 100644 index 000000000000..4d8a91911531 --- /dev/null +++ b/toolkit/components/mediasniffer/nsMediaSniffer.h @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 tw=80 et cindent: */ +/* 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/. */ + + +#include "nsIModule.h" +#include "nsIFactory.h" + +#include "nsIComponentManager.h" +#include "nsIComponentRegistrar.h" +#include "nsIContentSniffer.h" + +// ed905ba3-c656-480e-934e-6bc35bd36aff +#define NS_MEDIA_SNIFFER_CID \ +{0x3fdd6c28, 0x5b87, 0x4e3e, \ +{0x8b, 0x57, 0x8e, 0x83, 0xc2, 0x3c, 0x1a, 0x6d}} + +#define NS_MEDIA_SNIFFER_CONTRACTID "@mozilla.org/media/sniffer;1" + +class nsMediaSniffer : public nsIContentSniffer +{ + public: + NS_DECL_ISUPPORTS + NS_DECL_NSICONTENTSNIFFER + protected: + ~nsMediaSniffer() {}; + +#define PATTERN_ENTRY(mask, pattern, contentType) \ + {(const PRUint8*)mask, (const PRUint8*)pattern, sizeof(mask) - 1, contentType} + + struct nsMediaSnifferEntry { + const PRUint8* mMask; + const PRUint8* mPattern; + const PRUint32 mLength; + const char* mContentType; + }; + + static nsMediaSnifferEntry sSnifferEntries[]; +}; diff --git a/toolkit/components/mediasniffer/nsMediaSnifferModule.cpp b/toolkit/components/mediasniffer/nsMediaSnifferModule.cpp new file mode 100644 index 000000000000..b8dcf5d1e4c9 --- /dev/null +++ b/toolkit/components/mediasniffer/nsMediaSnifferModule.cpp @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* 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/. */ + +#include "mozilla/ModuleUtils.h" + +#include "nsMediaSniffer.h" + +NS_GENERIC_FACTORY_CONSTRUCTOR(nsMediaSniffer) + +NS_DEFINE_NAMED_CID(NS_MEDIA_SNIFFER_CID); + +static const mozilla::Module::CIDEntry kMediaSnifferCIDs[] = { + { &kNS_MEDIA_SNIFFER_CID, false, NULL, nsMediaSnifferConstructor }, + { NULL } +}; + +static const mozilla::Module::ContractIDEntry kMediaSnifferContracts[] = { + { NS_MEDIA_SNIFFER_CONTRACTID, &kNS_MEDIA_SNIFFER_CID }, + { NULL } +}; + +static const mozilla::Module::CategoryEntry kMediaSnifferCategories[] = { + { "content-sniffing-services", NS_MEDIA_SNIFFER_CONTRACTID, NS_MEDIA_SNIFFER_CONTRACTID}, + { "net-content-sniffers", NS_MEDIA_SNIFFER_CONTRACTID, NS_MEDIA_SNIFFER_CONTRACTID}, + { NULL } +}; + +static const mozilla::Module kMediaSnifferModule = { + mozilla::Module::kVersion, + kMediaSnifferCIDs, + kMediaSnifferContracts, + kMediaSnifferCategories +}; + +NSMODULE_DEFN(nsMediaSnifferModule) = &kMediaSnifferModule; diff --git a/toolkit/library/Makefile.in b/toolkit/library/Makefile.in index cd20833348b2..269e69b2e3a4 100644 --- a/toolkit/library/Makefile.in +++ b/toolkit/library/Makefile.in @@ -142,6 +142,7 @@ COMPONENT_LIBS += \ htmlpars \ identity \ imglib2 \ + mediasniffer \ gkgfx \ gklayout \ docshell \ diff --git a/toolkit/library/nsStaticXULComponents.cpp b/toolkit/library/nsStaticXULComponents.cpp index dea1e1e9def7..968958dc2083 100644 --- a/toolkit/library/nsStaticXULComponents.cpp +++ b/toolkit/library/nsStaticXULComponents.cpp @@ -180,6 +180,7 @@ MODULE(nsWindowDataSourceModule) \ MODULE(nsParserModule) \ MODULE(nsImageLib2Module) \ + MODULE(nsMediaSnifferModule) \ MODULE(nsGfxModule) \ PROFILER_MODULE \ WIDGET_MODULES \ From 7d605f68fd50bc88f2be949d87de24ff007fee9f Mon Sep 17 00:00:00 2001 From: Paul Adenot Date: Tue, 7 Aug 2012 15:56:01 -0700 Subject: [PATCH 111/169] Bug 567077 - Avoid sniffing when recreating a channel. r=cpearce --- .../html/content/public/nsHTMLMediaElement.h | 12 ++++++++++ .../html/content/src/nsHTMLMediaElement.cpp | 15 ++++++++---- content/media/MediaResource.cpp | 24 ++++++++++++++----- 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/content/html/content/public/nsHTMLMediaElement.h b/content/html/content/public/nsHTMLMediaElement.h index 0f6c1f262395..264fc194235b 100644 --- a/content/html/content/public/nsHTMLMediaElement.h +++ b/content/html/content/public/nsHTMLMediaElement.h @@ -312,6 +312,11 @@ public: static bool IsMediaPluginsType(const nsACString& aType); #endif + /** + * Get the mime type for this element. + */ + void GetMimeType(nsCString& aMimeType); + /** * Called when a child source element is added to this media element. This * may queue a task to run the select resource algorithm if appropriate. @@ -872,6 +877,13 @@ protected: // True if the media's channel's download has been suspended. bool mDownloadSuspendedByCache; + + // The Content-Type for this media. When we are sniffing for the Content-Type, + // and we are recreating a channel after the initial load, we need that + // information to give it as a hint to the channel for it to bypass the + // sniffing phase, that would fail because sniffing only works when applied to + // the first bytes of the stream. + nsCString mMimeType; }; #endif diff --git a/content/html/content/src/nsHTMLMediaElement.cpp b/content/html/content/src/nsHTMLMediaElement.cpp index 15635ea983e3..b58f2cc6b0ef 100644 --- a/content/html/content/src/nsHTMLMediaElement.cpp +++ b/content/html/content/src/nsHTMLMediaElement.cpp @@ -2419,19 +2419,21 @@ nsresult nsHTMLMediaElement::InitializeDecoderForChannel(nsIChannel *aChannel, NS_ASSERTION(mDecoder == nullptr, "Shouldn't have a decoder"); nsCAutoString mimeType; - aChannel->GetContentType(mimeType); - nsRefPtr decoder = CreateDecoder(mimeType); + aChannel->GetContentType(mMimeType); + NS_ASSERTION(!mMimeType.IsEmpty(), "We should have the Content-Type."); + + nsRefPtr decoder = CreateDecoder(mMimeType); if (!decoder) { nsAutoString src; GetCurrentSrc(src); - NS_ConvertUTF8toUTF16 mimeUTF16(mimeType); + NS_ConvertUTF8toUTF16 mimeUTF16(mMimeType); const PRUnichar* params[] = { mimeUTF16.get(), src.get() }; ReportLoadError("MediaLoadUnsupportedMimeType", params, ArrayLength(params)); return NS_ERROR_FAILURE; } - LOG(PR_LOG_DEBUG, ("%p Created decoder %p for type %s", this, decoder.get(), mimeType.get())); + LOG(PR_LOG_DEBUG, ("%p Created decoder %p for type %s", this, decoder.get(), mMimeType.get())); MediaResource* resource = MediaResource::Create(decoder, aChannel); if (!resource) @@ -3507,6 +3509,11 @@ NS_IMETHODIMP nsHTMLMediaElement::GetMozFragmentEnd(double *aTime) return NS_OK; } +void nsHTMLMediaElement::GetMimeType(nsCString& aMimeType) +{ + aMimeType = mMimeType; +} + void nsHTMLMediaElement::NotifyAudioAvailableListener() { if (mDecoder) { diff --git a/content/media/MediaResource.cpp b/content/media/MediaResource.cpp index db01f70d8b6e..457957d1ab4f 100644 --- a/content/media/MediaResource.cpp +++ b/content/media/MediaResource.cpp @@ -688,12 +688,24 @@ ChannelMediaResource::RecreateChannel() nsCOMPtr loadGroup = element->GetDocumentLoadGroup(); NS_ENSURE_TRUE(loadGroup, NS_ERROR_NULL_POINTER); - return NS_NewChannel(getter_AddRefs(mChannel), - mURI, - nullptr, - loadGroup, - nullptr, - loadFlags); + nsresult rv = NS_NewChannel(getter_AddRefs(mChannel), + mURI, + nsnull, + loadGroup, + nsnull, + loadFlags); + + // We have cached the Content-Type, which should not change. Give a hint to + // the channel to avoid a sniffing failure, which would be expected because we + // are probably seeking in the middle of the bitstream, and sniffing relies + // on the presence of a magic number at the beginning of the stream. + nsCAutoString contentType; + element->GetMimeType(contentType); + NS_ASSERTION(!contentType.IsEmpty(), + "When recreating a channel, we should know the Content-Type."); + mChannel->SetContentType(contentType); + + return rv; } void From 886438d841918376ecc0270e2ade36cee518488c Mon Sep 17 00:00:00 2001 From: Paul Adenot Date: Tue, 7 Aug 2012 15:56:25 -0700 Subject: [PATCH 112/169] Bug 567077 - Sniff types of media files that are served with no Content-Type -- Tests r=cpearce --- content/media/test/Makefile.in | 3 + content/media/test/contentType.sjs | 77 +++++++++++++++++++++ content/media/test/id3tags.mp3 | Bin 0 -> 3530 bytes content/media/test/manifest.js | 13 ++++ content/media/test/notags.mp3 | Bin 0 -> 2506 bytes content/media/test/short.mp4 | Bin 0 -> 29435 bytes content/media/test/test_media_sniffer.html | 70 +++++++++++++++++++ 7 files changed, 163 insertions(+) create mode 100644 content/media/test/contentType.sjs create mode 100644 content/media/test/id3tags.mp3 create mode 100644 content/media/test/notags.mp3 create mode 100644 content/media/test/short.mp4 create mode 100644 content/media/test/test_media_sniffer.html diff --git a/content/media/test/Makefile.in b/content/media/test/Makefile.in index d0f1727f33e1..377d38f4f94f 100644 --- a/content/media/test/Makefile.in +++ b/content/media/test/Makefile.in @@ -215,6 +215,9 @@ MOCHITEST_FILES += \ video-overhang.ogg \ file_a4_tone.ogg \ detodos.opus \ + short.mp4 \ + notags.mp3 \ + id3tags.mp3 \ $(NULL) # Wave sample files diff --git a/content/media/test/contentType.sjs b/content/media/test/contentType.sjs new file mode 100644 index 000000000000..b6eb757c3c9b --- /dev/null +++ b/content/media/test/contentType.sjs @@ -0,0 +1,77 @@ +// Parse the query string, and give us the value for a certain key, or false if +// it does not exist. +function parseQuery(request, key) { + var params = request.queryString.split('?')[0].split('&'); + for (var j = 0; j < params.length; ++j) { + var p = params[j]; + if (p == key) + return true; + if (p.indexOf(key + "=") == 0) + return p.substring(key.length + 1); + if (p.indexOf("=") < 0 && key == "") + return p; + } + return false; +} + +function handleRequest(request, response) { + try { + // Get the filename to send back. + var filename = parseQuery(request, "file"); + + const CC = Components.Constructor; + const BinaryOutputStream = CC("@mozilla.org/binaryoutputstream;1", + "nsIBinaryOutputStream", + "setOutputStream"); + var file = Components.classes["@mozilla.org/file/directory_service;1"]. + getService(Components.interfaces.nsIProperties). + get("CurWorkD", Components.interfaces.nsILocalFile); + var fis = Components.classes['@mozilla.org/network/file-input-stream;1']. + createInstance(Components.interfaces.nsIFileInputStream); + var bis = Components.classes["@mozilla.org/binaryinputstream;1"]. + createInstance(Components.interfaces.nsIBinaryInputStream); + var paths = "tests/content/media/test/" + filename; + dump(paths + '\n'); + var split = paths.split("/"); + for(var i = 0; i < split.length; ++i) { + file.append(split[i]); + } + fis.init(file, -1, -1, false); + + // handle range requests + var partialstart = 0, + partialend = file.fileSize - 1; + if (request.hasHeader("Range")) { + var range = request.getHeader("Range"); + var parts = range.replace(/bytes=/, "").split("-"); + var partialstart = parts[0]; + var partialend = parts[1]; + if (!partialend.length) { + partialend = file.fileSize - 1; + } + response.setStatusLine(request.httpVersion, 206, "Partial Content"); + var contentRange = "bytes " + partialstart + "-" + partialend + "/" + file.fileSize; + response.setHeader("Content-Range", contentRange); + } + + fis.seek(Components.interfaces.nsISeekableStream.NS_SEEK_SET, partialstart); + bis.setInputStream(fis); + + var sendContentType = parseQuery(request, "nomime"); + if (sendContentType == false) { + var contentType = parseQuery(request, "type"); + if (contentType == false) { + // This should not happen. + dump("No type specified without having \'nomime\' in parameters."); + return; + } + response.setHeader("Content-Type", contentType, false); + } + response.setHeader("Content-Length", ""+bis.available(), false); + + var bytes = bis.readBytes(bis.available()); + response.write(bytes, bytes.length); + } catch (e) { + dump ("ERROR : " + e + "\n"); + } +} diff --git a/content/media/test/id3tags.mp3 b/content/media/test/id3tags.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..bad506cf185478c9c903793d11d95f278148e007 GIT binary patch literal 3530 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 LXPn(H{U7)@tPzX8 literal 0 HcmV?d00001 diff --git a/content/media/test/short.mp4 b/content/media/test/short.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..0b9870bdcb500389b78a84e7feb6cce31fd828b4 GIT binary patch literal 29435 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 + + + Media test: mozStopDownload + + + + + + + + + + +
    +
    +
    + + From 8184d80a9a2cfe370b3066bc5401d29e5cd26cd1 Mon Sep 17 00:00:00 2001 From: Paul Adenot Date: Tue, 7 Aug 2012 18:00:28 -0700 Subject: [PATCH 113/169] Bug 567077 - Fix an assertion failure when the decoder was cloned. r=cpearce --- content/html/content/src/nsHTMLMediaElement.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/content/html/content/src/nsHTMLMediaElement.cpp b/content/html/content/src/nsHTMLMediaElement.cpp index b58f2cc6b0ef..47137b4477c5 100644 --- a/content/html/content/src/nsHTMLMediaElement.cpp +++ b/content/html/content/src/nsHTMLMediaElement.cpp @@ -1041,6 +1041,11 @@ nsresult nsHTMLMediaElement::LoadResource() if (other) { // Clone it. nsresult rv = InitializeDecoderAsClone(other->mDecoder); + // Get the mimetype from the element we clone, since we will not get it via + // the channel, and we won't be able to sniff for it, because we will not + // open a channel to get the beginning of the media (it is likely to already + // be in the cache). + mMimeType = other->mMimeType; if (NS_SUCCEEDED(rv)) return rv; } From d4653b4f4380f4139f805543c0441e98ded56573 Mon Sep 17 00:00:00 2001 From: Kyle Machulis Date: Tue, 7 Aug 2012 21:07:57 -0700 Subject: [PATCH 114/169] Bug 778384: Hook bluetooth up to permissions manager; r=mrbkap --- dom/bluetooth/BluetoothManager.cpp | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/dom/bluetooth/BluetoothManager.cpp b/dom/bluetooth/BluetoothManager.cpp index c540eff5142c..1c9abb8d1889 100644 --- a/dom/bluetooth/BluetoothManager.cpp +++ b/dom/bluetooth/BluetoothManager.cpp @@ -13,8 +13,8 @@ #include "BluetoothReplyRunnable.h" #include "nsContentUtils.h" -#include "mozilla/Preferences.h" #include "nsIDOMDOMRequest.h" +#include "nsIPermissionManager.h" #include "nsDOMClassInfo.h" #include "nsDOMEvent.h" #include "nsThreadUtils.h" @@ -22,10 +22,7 @@ #include "mozilla/LazyIdleThread.h" #include "mozilla/Util.h" -#define DOM_BLUETOOTH_URL_PREF "dom.mozBluetooth.whitelist" - using namespace mozilla; -using mozilla::Preferences; USING_BLUETOOTH_NAMESPACE @@ -276,11 +273,27 @@ NS_NewBluetoothManager(nsPIDOMWindow* aWindow, { NS_ASSERTION(aWindow, "Null pointer!"); - bool allowed; - nsresult rv = nsContentUtils::IsOnPrefWhitelist(aWindow, DOM_BLUETOOTH_URL_PREF, &allowed); + nsPIDOMWindow* innerWindow = aWindow->IsInnerWindow() ? + aWindow : + aWindow->GetCurrentInnerWindow(); + + // Need the document for security check. + nsCOMPtr document = innerWindow->GetExtantDoc(); + NS_ENSURE_TRUE(document, NS_NOINTERFACE); + + nsCOMPtr principal = document->NodePrincipal(); + NS_ENSURE_TRUE(principal, NS_ERROR_UNEXPECTED); + + nsCOMPtr permMgr = + do_GetService(NS_PERMISSIONMANAGER_CONTRACTID); + NS_ENSURE_TRUE(permMgr, NS_ERROR_UNEXPECTED); + + PRUint32 permission; + nsresult rv = + permMgr->TestPermissionFromPrincipal(principal, "mozBluetooth", &permission); NS_ENSURE_SUCCESS(rv, rv); - if (!allowed) { + if (permission != nsIPermissionManager::ALLOW_ACTION) { *aBluetoothManager = nullptr; return NS_OK; } @@ -290,6 +303,7 @@ NS_NewBluetoothManager(nsPIDOMWindow* aWindow, NS_ERROR("Cannot create bluetooth manager!"); return NS_ERROR_FAILURE; } + bluetoothManager.forget(aBluetoothManager); return NS_OK; } From 936a7d3c339fa2e65574125872c81c12c026b0a9 Mon Sep 17 00:00:00 2001 From: Kyle Machulis Date: Tue, 7 Aug 2012 21:10:25 -0700 Subject: [PATCH 115/169] Backing out 936cfbd263b2, wrong commit message --- dom/bluetooth/BluetoothManager.cpp | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/dom/bluetooth/BluetoothManager.cpp b/dom/bluetooth/BluetoothManager.cpp index 1c9abb8d1889..c540eff5142c 100644 --- a/dom/bluetooth/BluetoothManager.cpp +++ b/dom/bluetooth/BluetoothManager.cpp @@ -13,8 +13,8 @@ #include "BluetoothReplyRunnable.h" #include "nsContentUtils.h" +#include "mozilla/Preferences.h" #include "nsIDOMDOMRequest.h" -#include "nsIPermissionManager.h" #include "nsDOMClassInfo.h" #include "nsDOMEvent.h" #include "nsThreadUtils.h" @@ -22,7 +22,10 @@ #include "mozilla/LazyIdleThread.h" #include "mozilla/Util.h" +#define DOM_BLUETOOTH_URL_PREF "dom.mozBluetooth.whitelist" + using namespace mozilla; +using mozilla::Preferences; USING_BLUETOOTH_NAMESPACE @@ -273,27 +276,11 @@ NS_NewBluetoothManager(nsPIDOMWindow* aWindow, { NS_ASSERTION(aWindow, "Null pointer!"); - nsPIDOMWindow* innerWindow = aWindow->IsInnerWindow() ? - aWindow : - aWindow->GetCurrentInnerWindow(); - - // Need the document for security check. - nsCOMPtr document = innerWindow->GetExtantDoc(); - NS_ENSURE_TRUE(document, NS_NOINTERFACE); - - nsCOMPtr principal = document->NodePrincipal(); - NS_ENSURE_TRUE(principal, NS_ERROR_UNEXPECTED); - - nsCOMPtr permMgr = - do_GetService(NS_PERMISSIONMANAGER_CONTRACTID); - NS_ENSURE_TRUE(permMgr, NS_ERROR_UNEXPECTED); - - PRUint32 permission; - nsresult rv = - permMgr->TestPermissionFromPrincipal(principal, "mozBluetooth", &permission); + bool allowed; + nsresult rv = nsContentUtils::IsOnPrefWhitelist(aWindow, DOM_BLUETOOTH_URL_PREF, &allowed); NS_ENSURE_SUCCESS(rv, rv); - if (permission != nsIPermissionManager::ALLOW_ACTION) { + if (!allowed) { *aBluetoothManager = nullptr; return NS_OK; } @@ -303,7 +290,6 @@ NS_NewBluetoothManager(nsPIDOMWindow* aWindow, NS_ERROR("Cannot create bluetooth manager!"); return NS_ERROR_FAILURE; } - bluetoothManager.forget(aBluetoothManager); return NS_OK; } From 3df54ef3d4ab3a24a20ad9f25bf157b7e8820917 Mon Sep 17 00:00:00 2001 From: Kyle Machulis Date: Tue, 7 Aug 2012 21:10:36 -0700 Subject: [PATCH 116/169] Bug 779384: Hook bluetooth up to permissions manager; r=mrbkap --- dom/bluetooth/BluetoothManager.cpp | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/dom/bluetooth/BluetoothManager.cpp b/dom/bluetooth/BluetoothManager.cpp index c540eff5142c..1c9abb8d1889 100644 --- a/dom/bluetooth/BluetoothManager.cpp +++ b/dom/bluetooth/BluetoothManager.cpp @@ -13,8 +13,8 @@ #include "BluetoothReplyRunnable.h" #include "nsContentUtils.h" -#include "mozilla/Preferences.h" #include "nsIDOMDOMRequest.h" +#include "nsIPermissionManager.h" #include "nsDOMClassInfo.h" #include "nsDOMEvent.h" #include "nsThreadUtils.h" @@ -22,10 +22,7 @@ #include "mozilla/LazyIdleThread.h" #include "mozilla/Util.h" -#define DOM_BLUETOOTH_URL_PREF "dom.mozBluetooth.whitelist" - using namespace mozilla; -using mozilla::Preferences; USING_BLUETOOTH_NAMESPACE @@ -276,11 +273,27 @@ NS_NewBluetoothManager(nsPIDOMWindow* aWindow, { NS_ASSERTION(aWindow, "Null pointer!"); - bool allowed; - nsresult rv = nsContentUtils::IsOnPrefWhitelist(aWindow, DOM_BLUETOOTH_URL_PREF, &allowed); + nsPIDOMWindow* innerWindow = aWindow->IsInnerWindow() ? + aWindow : + aWindow->GetCurrentInnerWindow(); + + // Need the document for security check. + nsCOMPtr document = innerWindow->GetExtantDoc(); + NS_ENSURE_TRUE(document, NS_NOINTERFACE); + + nsCOMPtr principal = document->NodePrincipal(); + NS_ENSURE_TRUE(principal, NS_ERROR_UNEXPECTED); + + nsCOMPtr permMgr = + do_GetService(NS_PERMISSIONMANAGER_CONTRACTID); + NS_ENSURE_TRUE(permMgr, NS_ERROR_UNEXPECTED); + + PRUint32 permission; + nsresult rv = + permMgr->TestPermissionFromPrincipal(principal, "mozBluetooth", &permission); NS_ENSURE_SUCCESS(rv, rv); - if (!allowed) { + if (permission != nsIPermissionManager::ALLOW_ACTION) { *aBluetoothManager = nullptr; return NS_OK; } @@ -290,6 +303,7 @@ NS_NewBluetoothManager(nsPIDOMWindow* aWindow, NS_ERROR("Cannot create bluetooth manager!"); return NS_ERROR_FAILURE; } + bluetoothManager.forget(aBluetoothManager); return NS_OK; } From 14894fb5f2b5adcd610bdaa42accb5ed4542f844 Mon Sep 17 00:00:00 2001 From: Kyle Machulis Date: Tue, 7 Aug 2012 21:16:03 -0700 Subject: [PATCH 117/169] Bug 759883 - [b2g-bluetooth] Divide out bluetooth specifics from DBusThread object; r=echou --- dom/bluetooth/linux/BluetoothDBusService.cpp | 37 +++++++++++++-- ipc/dbus/DBusThread.cpp | 50 -------------------- 2 files changed, 34 insertions(+), 53 deletions(-) diff --git a/dom/bluetooth/linux/BluetoothDBusService.cpp b/dom/bluetooth/linux/BluetoothDBusService.cpp index 3e9f2a78eb74..9b9a077b24e0 100644 --- a/dom/bluetooth/linux/BluetoothDBusService.cpp +++ b/dom/bluetooth/linux/BluetoothDBusService.cpp @@ -338,7 +338,9 @@ GetProperty(DBusMessageIter aIter, Properties* aPropertyTypes, // This happens when the array is 0-length. Apparently we get a // DBUS_TYPE_INVALID type. propertyValue = InfallibleTArray(); +#ifdef DEBUG NS_WARNING("Received array type that's not a string array!"); +#endif } break; default: @@ -605,7 +607,7 @@ BluetoothDBusService::StartInternal() } if (mConnection) { - return NS_OK; + return NS_OK; } if (NS_FAILED(EstablishDBusConnection())) { @@ -613,7 +615,23 @@ BluetoothDBusService::StartInternal() StopDBus(); return NS_ERROR_FAILURE; } - + + DBusError err; + dbus_error_init(&err); + + // Set which messages will be processed by this dbus connection. + // Since we are maintaining a single thread for all the DBus bluez + // signals we want, register all of them in this thread at startup. + // The event handler will sort the destinations out as needed. + for (uint32_t i = 0; i < ArrayLength(sBluetoothDBusSignals); ++i) { + dbus_bus_add_match(mConnection, + sBluetoothDBusSignals[i], + &err); + if (dbus_error_is_set(&err)) { + LOG_AND_FREE_DBUS_ERROR(&err); + } + } + // Add a filter for all incoming messages_base if (!dbus_connection_add_filter(mConnection, EventFilter, NULL, NULL)) { @@ -634,7 +652,20 @@ BluetoothDBusService::StopInternal() StopDBus(); return NS_OK; } - dbus_connection_remove_filter(mConnection, EventFilter, NULL); + + DBusError err; + dbus_error_init(&err); + for (uint32_t i = 0; i < ArrayLength(sBluetoothDBusSignals); ++i) { + dbus_bus_remove_match(mConnection, + sBluetoothDBusSignals[i], + &err); + if (dbus_error_is_set(&err)) { + LOG_AND_FREE_DBUS_ERROR(&err); + } + } + + dbus_connection_remove_filter(mConnection, EventFilter, nullptr); + mConnection = nullptr; mBluetoothSignalObserverTable.Clear(); StopDBus(); diff --git a/ipc/dbus/DBusThread.cpp b/ipc/dbus/DBusThread.cpp index 9bc5a6d748eb..5c42b5149297 100644 --- a/ipc/dbus/DBusThread.cpp +++ b/ipc/dbus/DBusThread.cpp @@ -77,21 +77,6 @@ enum { DBUS_EVENT_LOOP_REMOVE = 3, } DBusEventTypes; -// Signals that the DBus thread should listen for. Needs to include -// all signals any DBus observer object may need. - -static const char* DBUS_SIGNALS[] = -{ - "type='signal',interface='org.bluez.Adapter'", - "type='signal',interface='org.bluez.Manager'", - "type='signal',interface='org.bluez.Device'", - "type='signal',interface='org.bluez.Input'", - "type='signal',interface='org.bluez.Network'", - "type='signal',interface='org.bluez.NetworkServer'", - "type='signal',interface='org.bluez.HealthDevice'", - "type='signal',interface='org.bluez.AudioSink'" -}; - static unsigned int UnixEventsToDBusFlags(short events) { return (events & DBUS_WATCH_READABLE ? POLLIN : 0) | @@ -150,7 +135,6 @@ struct DBusThread : public RawDBusConnection protected: bool SetUpEventLoop(); bool TearDownData(); - bool TearDownEventLoop(); }; static nsAutoPtr sDBusThread; @@ -322,19 +306,6 @@ DBusThread::SetUpEventLoop() return false; } - // Set which messages will be processed by this dbus connection. - // Since we are maintaining a single thread for all the DBus bluez - // signals we want, register all of them in this thread at startup. - // The event handler will sort the destinations out as needed. - for (uint32_t i = 0; i < ArrayLength(DBUS_SIGNALS); ++i) { - dbus_bus_add_match(mConnection, - DBUS_SIGNALS[i], - &err); - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - return false; - } - } return true; } @@ -356,26 +327,6 @@ DBusThread::TearDownData() return true; } -bool -DBusThread::TearDownEventLoop() -{ - MOZ_ASSERT(mConnection); - - DBusError err; - dbus_error_init(&err); - - for (uint32_t i = 0; i < ArrayLength(DBUS_SIGNALS); ++i) { - dbus_bus_remove_match(mConnection, - DBUS_SIGNALS[i], - &err); - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - } - } - - return true; -} - void DBusThread::EventLoop() { @@ -400,7 +351,6 @@ DBusThread::EventLoop() LOG("DBus Event Loop Exiting\n"); dbus_connection_set_watch_functions(mConnection, NULL, NULL, NULL, NULL, NULL); - TearDownEventLoop(); return; case DBUS_EVENT_LOOP_ADD: HandleWatchAdd(this); From de6f5f272e7a204287c52c8fb9d9bea4c9ec2637 Mon Sep 17 00:00:00 2001 From: Eric Chou Date: Tue, 7 Aug 2012 21:19:07 -0700 Subject: [PATCH 118/169] Bug 780812 - [b2g-bluetooth] Implement function to get RFCOMM channel of specific Bluetooth service; r=qdot --- dom/bluetooth/BluetoothService.h | 5 +++++ dom/bluetooth/linux/BluetoothDBusService.cpp | 21 ++++++++++++++++++++ dom/bluetooth/linux/BluetoothDBusService.h | 4 ++++ ipc/dbus/DBusUtils.cpp | 16 +++++++++++++++ ipc/dbus/DBusUtils.h | 1 + 5 files changed, 47 insertions(+) diff --git a/dom/bluetooth/BluetoothService.h b/dom/bluetooth/BluetoothService.h index 6f62913b6139..fdeedcb35196 100644 --- a/dom/bluetooth/BluetoothService.h +++ b/dom/bluetooth/BluetoothService.h @@ -187,6 +187,11 @@ public: const nsAString& aDeviceAddress, nsAString& aDevicePath) = 0; + virtual int + GetDeviceServiceChannelInternal(const nsAString& aObjectPath, + const nsAString& aPattern, + int aAttributeId) = 0; + protected: BluetoothService() { diff --git a/dom/bluetooth/linux/BluetoothDBusService.cpp b/dom/bluetooth/linux/BluetoothDBusService.cpp index 9b9a077b24e0..0a3e08c3ca40 100644 --- a/dom/bluetooth/linux/BluetoothDBusService.cpp +++ b/dom/bluetooth/linux/BluetoothDBusService.cpp @@ -868,3 +868,24 @@ BluetoothDBusService::GetDevicePath(const nsAString& aAdapterPath, aDevicePath = GetObjectPathFromAddress(aAdapterPath, aDeviceAddress); return true; } + +int +BluetoothDBusService::GetDeviceServiceChannelInternal(const nsAString& aObjectPath, + const nsAString& aPattern, + int aAttributeId) +{ + // This is a blocking call, should not be run on main thread. + MOZ_ASSERT(!NS_IsMainThread()); + + const char* deviceObjectPath = NS_ConvertUTF16toUTF8(aObjectPath).get(); + const char* pattern = NS_ConvertUTF16toUTF8(aPattern).get(); + + DBusMessage *reply = + dbus_func_args(mConnection, deviceObjectPath, + DBUS_DEVICE_IFACE, "GetServiceAttributeValue", + DBUS_TYPE_STRING, &pattern, + DBUS_TYPE_UINT16, &aAttributeId, + DBUS_TYPE_INVALID); + + return reply ? dbus_returns_int32(reply) : -1; +} diff --git a/dom/bluetooth/linux/BluetoothDBusService.h b/dom/bluetooth/linux/BluetoothDBusService.h index aaf55a850c74..0d0153f8f0e8 100644 --- a/dom/bluetooth/linux/BluetoothDBusService.h +++ b/dom/bluetooth/linux/BluetoothDBusService.h @@ -44,6 +44,10 @@ public: GetDevicePath(const nsAString& aAdapterPath, const nsAString& aDeviceAddress, nsAString& aDevicePath); + virtual int + GetDeviceServiceChannelInternal(const nsAString& aObjectPath, + const nsAString& aPattern, + int aAttributeId); private: nsresult SendGetPropertyMessage(const nsAString& aPath, diff --git a/ipc/dbus/DBusUtils.cpp b/ipc/dbus/DBusUtils.cpp index f73e5f3db1ed..6f41f7697825 100644 --- a/ipc/dbus/DBusUtils.cpp +++ b/ipc/dbus/DBusUtils.cpp @@ -260,5 +260,21 @@ DBusMessage * dbus_func_args_error(DBusConnection *conn, return ret; } +int dbus_returns_int32(DBusMessage *reply) +{ + DBusError err; + int ret = -1; + + dbus_error_init(&err); + if (!dbus_message_get_args(reply, &err, + DBUS_TYPE_INT32, &ret, + DBUS_TYPE_INVALID)) { + LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply); + } + + dbus_message_unref(reply); + return ret; +} + } } diff --git a/ipc/dbus/DBusUtils.h b/ipc/dbus/DBusUtils.h index 79c16c208064..948f9d18a667 100644 --- a/ipc/dbus/DBusUtils.h +++ b/ipc/dbus/DBusUtils.h @@ -105,6 +105,7 @@ DBusMessage* dbus_func_args_timeout_valist(DBusConnection* conn, int first_arg_type, va_list args); +int dbus_returns_int32(DBusMessage *reply); } } From de8420fdc1599b4a9699bc5cb4e7859a3727b621 Mon Sep 17 00:00:00 2001 From: Steven Lee Date: Tue, 7 Aug 2012 19:37:00 -0400 Subject: [PATCH 119/169] Bug 714358: Time manager interface. f=mounir, sr=mounir --- dom/Makefile.in | 1 + dom/dom-config.mk | 1 + dom/interfaces/base/nsIDOMWindow.idl | 3 ++- dom/time/Makefile.in | 27 +++++++++++++++++++++++++++ dom/time/nsIDOMNavigatorTime.idl | 13 +++++++++++++ dom/time/nsIDOMTimeManager.idl | 12 ++++++++++++ toolkit/toolkit-makefiles.sh | 1 + 7 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 dom/time/Makefile.in create mode 100644 dom/time/nsIDOMNavigatorTime.idl create mode 100644 dom/time/nsIDOMTimeManager.idl diff --git a/dom/Makefile.in b/dom/Makefile.in index c210af5a9c8a..80ad3d41a166 100644 --- a/dom/Makefile.in +++ b/dom/Makefile.in @@ -61,6 +61,7 @@ DIRS += \ sms \ mms \ src \ + time \ locales \ network \ plugins/base \ diff --git a/dom/dom-config.mk b/dom/dom-config.mk index 92b372f88b0e..135fe09d2dfc 100644 --- a/dom/dom-config.mk +++ b/dom/dom-config.mk @@ -19,6 +19,7 @@ DOM_SRCDIRS = \ dom/src/geolocation \ dom/src/notification \ dom/workers \ + dom/time \ content/xbl/src \ content/xul/document/src \ content/events/src \ diff --git a/dom/interfaces/base/nsIDOMWindow.idl b/dom/interfaces/base/nsIDOMWindow.idl index b8ce47a8bcd7..1d2f286c9c62 100644 --- a/dom/interfaces/base/nsIDOMWindow.idl +++ b/dom/interfaces/base/nsIDOMWindow.idl @@ -32,7 +32,7 @@ interface nsIDOMMozURLProperty : nsISupports * @see */ -[scriptable, uuid(A1AF6CD9-C6E7-4037-99F8-DBCA1B03E345)] +[scriptable, uuid(AB4ED3B8-84F8-4585-B413-0996A7F96D20)] interface nsIDOMWindow : nsISupports { // the current browsing context @@ -496,6 +496,7 @@ interface nsIDOMWindow : nsISupports [implicit_jscontext] attribute jsval ondeviceproximity; [implicit_jscontext] attribute jsval onuserproximity; [implicit_jscontext] attribute jsval ondevicelight; + [implicit_jscontext] attribute jsval onmoztimechange; [implicit_jscontext] attribute jsval onmouseenter; [implicit_jscontext] attribute jsval onmouseleave; diff --git a/dom/time/Makefile.in b/dom/time/Makefile.in new file mode 100644 index 000000000000..0d037c447877 --- /dev/null +++ b/dom/time/Makefile.in @@ -0,0 +1,27 @@ +# 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/. + +DEPTH = ../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +LIBRARY_NAME = dom_time_s +XPIDL_MODULE = dom_time +LIBXUL_LIBRARY = 1 +FORCE_STATIC_LIB = 1 + +include $(topsrcdir)/dom/dom-config.mk + +CPPSRCS = $(NULL) + +XPIDLSRCS = \ + nsIDOMNavigatorTime.idl \ + nsIDOMTimeManager.idl \ + $(NULL) + +include $(topsrcdir)/config/config.mk +include $(topsrcdir)/config/rules.mk diff --git a/dom/time/nsIDOMNavigatorTime.idl b/dom/time/nsIDOMNavigatorTime.idl new file mode 100644 index 000000000000..49942463ed8e --- /dev/null +++ b/dom/time/nsIDOMNavigatorTime.idl @@ -0,0 +1,13 @@ +/* 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/. */ + +#include "nsISupports.idl" + +interface nsIDOMMozTimeManager; + +[scriptable, uuid(befc186d-c249-4acb-8e70-8080f7b45e5c)] +interface nsIDOMMozNavigatorTime : nsISupports +{ + readonly attribute nsIDOMMozTimeManager mozTime; +}; diff --git a/dom/time/nsIDOMTimeManager.idl b/dom/time/nsIDOMTimeManager.idl new file mode 100644 index 000000000000..e5d320675907 --- /dev/null +++ b/dom/time/nsIDOMTimeManager.idl @@ -0,0 +1,12 @@ +/* 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/. */ + +#include "nsISupports.idl" + +[scriptable, builtinclass, uuid(d29beaaa-bd54-4fd5-9f18-e0eedb1dc96d)] +interface nsIDOMMozTimeManager : nsISupports +{ + // jsval could be Date object or UTC seconds + void set(in jsval time); +}; diff --git a/toolkit/toolkit-makefiles.sh b/toolkit/toolkit-makefiles.sh index b47ac0f99e8e..bfa7e1a80b02 100644 --- a/toolkit/toolkit-makefiles.sh +++ b/toolkit/toolkit-makefiles.sh @@ -82,6 +82,7 @@ MAKEFILES_dom=" dom/src/storage/Makefile dom/system/Makefile dom/workers/Makefile + dom/time/Makefile " MAKEFILES_editor=" From 9242ba93860aba0ad499efbf0cdd2115d31b2599 Mon Sep 17 00:00:00 2001 From: Steven Lee Date: Tue, 7 Aug 2012 19:20:00 -0400 Subject: [PATCH 120/169] Bug 714358: System time change implementation, r=mounir --- dom/time/nsIDOMTimeManager.idl | 2 +- hal/Hal.cpp | 21 +++++++++++++++++++++ hal/Hal.h | 20 ++++++++++++++++++++ hal/HalTypes.h | 18 +++++++++++++++++- hal/gonk/GonkHal.cpp | 24 +++++++++++++++++++++++- hal/sandbox/PHal.ipdl | 2 ++ hal/sandbox/SandboxHal.cpp | 11 +++++++++++ 7 files changed, 95 insertions(+), 3 deletions(-) diff --git a/dom/time/nsIDOMTimeManager.idl b/dom/time/nsIDOMTimeManager.idl index e5d320675907..fd5138fb2c5b 100644 --- a/dom/time/nsIDOMTimeManager.idl +++ b/dom/time/nsIDOMTimeManager.idl @@ -8,5 +8,5 @@ interface nsIDOMMozTimeManager : nsISupports { // jsval could be Date object or UTC seconds - void set(in jsval time); + [implicit_jscontext] void set(in jsval time); }; diff --git a/hal/Hal.cpp b/hal/Hal.cpp index a5b6d732b142..a52f25a27ec6 100644 --- a/hal/Hal.cpp +++ b/hal/Hal.cpp @@ -417,7 +417,28 @@ bool GetLight(LightType light, hal::LightConfiguration* aConfig) RETURN_PROXY_IF_SANDBOXED(GetLight(light, aConfig)); } +static ObserverList sSystemTimeObserver; +void +RegisterSystemTimeChangeObserver(SystemTimeObserver *aObserver) +{ + AssertMainThread(); + sSystemTimeObserver.AddObserver(aObserver); +} + +void +UnregisterSystemTimeChangeObserver(SystemTimeObserver *aObserver) +{ + AssertMainThread(); + sSystemTimeObserver.RemoveObserver(aObserver); +} + +void +NotifySystemTimeChange(const hal::SystemTimeChange& aReason) +{ + sSystemTimeObserver.Broadcast(aReason); +} + void AdjustSystemClock(int32_t aDeltaMilliseconds) { diff --git a/hal/Hal.h b/hal/Hal.h index 84d96241a456..c039ae95858c 100644 --- a/hal/Hal.h +++ b/hal/Hal.h @@ -50,6 +50,8 @@ class WindowIdentifier; extern PRLogModuleInfo *sHalLog; #define HAL_LOG(msg) PR_LOG(mozilla::hal::sHalLog, PR_LOG_DEBUG, msg) +typedef Observer SystemTimeObserver; + } // namespace hal namespace MOZ_HAL_NAMESPACE { @@ -249,6 +251,24 @@ void AdjustSystemClock(int32_t aDeltaMilliseconds); */ void SetTimezone(const nsCString& aTimezoneSpec); +/** + * Register observer for system time changed notification. + * @param aObserver The observer that should be added. + */ +void RegisterSystemTimeChangeObserver(hal::SystemTimeObserver *aObserver); + +/** + * Unregister the observer for system time changed. + * @param aObserver The observer that should be removed. + */ +void UnregisterSystemTimeChangeObserver(hal::SystemTimeObserver *aObserver); + +/** + * Notify of a change in the system cloeck or time zone. + * @param aReason + */ +void NotifySystemTimeChange(const hal::SystemTimeChange& aReason); + /** * Reboot the device. */ diff --git a/hal/HalTypes.h b/hal/HalTypes.h index 1833297655a3..189f6e37b527 100644 --- a/hal/HalTypes.h +++ b/hal/HalTypes.h @@ -71,6 +71,13 @@ enum WakeLockControl { WAKE_LOCK_ADD_ONE = 1, }; +enum SystemTimeChange { + SYS_TIME_CHANGE_UNKNOWN = -1, + SYS_TIME_CHANGE_CLOCK, + SYS_TIME_CHANGE_TZ, + SYS_TIME_CHANGE_GUARD +}; + } // namespace hal } // namespace mozilla @@ -143,7 +150,16 @@ struct ParamTraits: mozilla::hal::NUM_PROCESS_PRIORITY> { }; - +/** + * SystemTimeChange serializer. + */ +template <> +struct ParamTraits + : public EnumSerializer +{}; + } // namespace IPC #endif // mozilla_hal_Types_h diff --git a/hal/gonk/GonkHal.cpp b/hal/gonk/GonkHal.cpp index 9ac8fc97bf4d..abecb162a73a 100644 --- a/hal/gonk/GonkHal.cpp +++ b/hal/gonk/GonkHal.cpp @@ -581,6 +581,10 @@ sys_clock_settime(clockid_t clk_id, const struct timespec *tp) void AdjustSystemClock(int32_t aDeltaMilliseconds) { + if (aDeltaMilliseconds == 0) { + return; + } + struct timespec now; // Preventing context switch before setting system clock @@ -600,16 +604,34 @@ AdjustSystemClock(int32_t aDeltaMilliseconds) now.tv_sec -= 1; } // we need to have root privilege. - sys_clock_settime(CLOCK_REALTIME, &now); + if (sys_clock_settime(CLOCK_REALTIME, &now) != 0) { + NS_ERROR("sys_clock_settime failed"); + return; + } + + hal::NotifySystemTimeChange(hal::SYS_TIME_CHANGE_CLOCK); +} + +bool +IsSameTimeZone(const nsCString& aTimezoneSpec) +{ + char timezone[32]; + property_get("persist.sys.timezone", timezone, ""); + return aTimezoneSpec.EqualsASCII(timezone); } void SetTimezone(const nsCString& aTimezoneSpec) { + if (IsSameTimeZone(aTimezoneSpec)) { + return; + } + property_set("persist.sys.timezone", aTimezoneSpec.get()); // this function is automatically called by the other time conversion // functions that depend on the timezone. To be safe, we call it manually. tzset(); + hal::NotifySystemTimeChange(hal::SYS_TIME_CHANGE_TZ); } // Nothing to do here. Gonk widgetry always listens for screen diff --git a/hal/sandbox/PHal.ipdl b/hal/sandbox/PHal.ipdl index 0e35bf2efaad..04cf048b75a8 100644 --- a/hal/sandbox/PHal.ipdl +++ b/hal/sandbox/PHal.ipdl @@ -24,6 +24,7 @@ using mozilla::hal::SwitchDevice; using mozilla::hal::ProcessPriority; using nsIntRect; using PRTime; +using mozilla::hal::SystemTimeChange; namespace mozilla { @@ -86,6 +87,7 @@ child: NotifyWakeLockChange(WakeLockInformation aWakeLockInfo); NotifyScreenConfigurationChange(ScreenConfiguration aScreenOrientation); NotifySwitchChange(SwitchEvent aEvent); + NotifySystemTimeChange(SystemTimeChange aReason); parent: Vibrate(uint32_t[] pattern, uint64_t[] id, PBrowser browser); diff --git a/hal/sandbox/SandboxHal.cpp b/hal/sandbox/SandboxHal.cpp index ed6bdfb63955..6a3aec8b183a 100644 --- a/hal/sandbox/SandboxHal.cpp +++ b/hal/sandbox/SandboxHal.cpp @@ -583,6 +583,11 @@ public: hal::SetProcessPriority(aPid, aPriority); return true; } + + void Notify(const SystemTimeChange& aReason) + { + unused << SendNotifySystemTimeChange(aReason); + } }; class HalChild : public PHalChild { @@ -619,6 +624,12 @@ public: hal::NotifySwitchChange(aEvent); return true; } + + virtual bool + RecvNotifySystemTimeChange(const SystemTimeChange& aReason) { + hal::NotifySystemTimeChange(aReason); + return true; + } }; bool From 2a3357c97f7da7132028ca79d35e8ec764d39359 Mon Sep 17 00:00:00 2001 From: Steven Lee Date: Tue, 7 Aug 2012 19:11:00 -0400 Subject: [PATCH 121/169] Bug 714358: Time manager implementation. r=jlebar --- b2g/installer/package-manifest.in | 1 + content/base/src/nsGkAtomList.h | 1 + content/events/public/nsEventNameList.h | 4 + content/events/src/nsDOMEvent.cpp | 3 +- content/events/src/nsDOMEvent.h | 3 +- content/events/src/nsEventListenerManager.cpp | 32 ++++++- content/events/src/nsEventListenerManager.h | 3 + dom/base/Navigator.cpp | 57 ++++++++---- dom/base/Navigator.h | 9 ++ dom/base/nsDOMClassInfo.cpp | 9 ++ dom/base/nsDOMClassInfoClasses.h | 2 + dom/base/nsGlobalWindow.cpp | 14 +++ dom/base/nsGlobalWindow.h | 3 + dom/base/nsPIDOMWindow.h | 3 + dom/time/Makefile.in | 10 ++- dom/time/TimeChangeObserver.cpp | 87 +++++++++++++++++++ dom/time/TimeChangeObserver.h | 29 +++++++ dom/time/TimeManager.cpp | 57 ++++++++++++ dom/time/TimeManager.h | 31 +++++++ dom/time/nsIDOMTimeManager.idl | 10 ++- layout/build/Makefile.in | 1 + widget/nsGUIEvent.h | 3 + 22 files changed, 352 insertions(+), 20 deletions(-) create mode 100644 dom/time/TimeChangeObserver.cpp create mode 100644 dom/time/TimeChangeObserver.h create mode 100644 dom/time/TimeManager.cpp create mode 100644 dom/time/TimeManager.h diff --git a/b2g/installer/package-manifest.in b/b2g/installer/package-manifest.in index 097717e73e5a..79071a967efa 100644 --- a/b2g/installer/package-manifest.in +++ b/b2g/installer/package-manifest.in @@ -201,6 +201,7 @@ @BINPATH@/components/dom_xpath.xpt @BINPATH@/components/dom_xul.xpt @BINPATH@/components/dom_loadsave.xpt +@BINPATH@/components/dom_time.xpt @BINPATH@/components/downloads.xpt @BINPATH@/components/editor.xpt @BINPATH@/components/embed_base.xpt diff --git a/content/base/src/nsGkAtomList.h b/content/base/src/nsGkAtomList.h index dacaf51f5cd1..ded8059f8ba9 100644 --- a/content/base/src/nsGkAtomList.h +++ b/content/base/src/nsGkAtomList.h @@ -683,6 +683,7 @@ GK_ATOM(onmozfullscreenchange, "onmozfullscreenchange") GK_ATOM(onmozfullscreenerror, "onmozfullscreenerror") GK_ATOM(onmozpointerlockchange, "onmozpointerlockchange") GK_ATOM(onmozpointerlockerror, "onmozpointerlockerror") +GK_ATOM(onmoztimechange, "onmoztimechange") GK_ATOM(onMozMousePixelScroll, "onMozMousePixelScroll") GK_ATOM(onMozScrolledAreaChanged, "onMozScrolledAreaChanged") GK_ATOM(ononline, "ononline") diff --git a/content/events/public/nsEventNameList.h b/content/events/public/nsEventNameList.h index 10e7f68fe428..28d65df9f4ca 100644 --- a/content/events/public/nsEventNameList.h +++ b/content/events/public/nsEventNameList.h @@ -435,6 +435,10 @@ WINDOW_ONLY_EVENT(devicelight, NS_DEVICE_LIGHT, EventNameType_None, NS_EVENT) +WINDOW_ONLY_EVENT(moztimechange, + NS_MOZ_TIME_CHANGE_EVENT, + EventNameType_None, + NS_EVENT) TOUCH_EVENT(touchstart, NS_TOUCH_START, diff --git a/content/events/src/nsDOMEvent.cpp b/content/events/src/nsDOMEvent.cpp index f542a6b67dd7..4f51b888bf8a 100644 --- a/content/events/src/nsDOMEvent.cpp +++ b/content/events/src/nsDOMEvent.cpp @@ -97,7 +97,8 @@ static const char* const sEventNames[] = { "deviceorientation", "deviceproximity", "userproximity", - "devicelight" + "devicelight", + "moztimechange" }; static char *sPopupAllowedEvents; diff --git a/content/events/src/nsDOMEvent.h b/content/events/src/nsDOMEvent.h index c01d57b56b90..5381ed0707cf 100644 --- a/content/events/src/nsDOMEvent.h +++ b/content/events/src/nsDOMEvent.h @@ -177,7 +177,8 @@ public: eDOMEvents_deviceorientation, eDOMEvents_deviceproximity, eDOMEvents_userproximity, - eDOMEvents_devicelight + eDOMEvents_devicelight, + eDOMEvents_moztimechange }; nsDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent); diff --git a/content/events/src/nsEventListenerManager.cpp b/content/events/src/nsEventListenerManager.cpp index 78697870fded..1150ff4e6533 100644 --- a/content/events/src/nsEventListenerManager.cpp +++ b/content/events/src/nsEventListenerManager.cpp @@ -53,6 +53,7 @@ #include "nsIContentSecurityPolicy.h" #include "nsJSEnvironment.h" #include "xpcpublic.h" +#include "TimeChangeObserver.h" using namespace mozilla::dom; using namespace mozilla::hal; @@ -271,6 +272,8 @@ nsEventListenerManager::AddEventListener(nsIDOMEventListener *aListener, EnableDevice(NS_DEVICE_LIGHT); } else if (aTypeAtom == nsGkAtoms::ondevicemotion) { EnableDevice(NS_DEVICE_MOTION); + } else if (aTypeAtom == nsGkAtoms::onmoztimechange) { + EnableTimeChangeNotifications(); } else if ((aType >= NS_MOZTOUCH_DOWN && aType <= NS_MOZTOUCH_UP) || (aTypeAtom == nsGkAtoms::ontouchstart || aTypeAtom == nsGkAtoms::ontouchend || @@ -396,6 +399,7 @@ nsEventListenerManager::RemoveEventListener(nsIDOMEventListener *aListener, PRUint32 count = mListeners.Length(); PRUint32 typeCount = 0; bool deviceType = IsDeviceType(aType); + bool timeChangeEvent = (aType == NS_MOZ_TIME_CHANGE_EVENT); for (PRUint32 i = 0; i < count; ++i) { ls = &mListeners.ElementAt(i); @@ -409,7 +413,7 @@ nsEventListenerManager::RemoveEventListener(nsIDOMEventListener *aListener, mNoListenerForEvent = NS_EVENT_TYPE_NULL; mNoListenerForEventAtom = nullptr; - if (!deviceType) { + if (!deviceType && !timeChangeEvent) { return; } --typeCount; @@ -419,6 +423,8 @@ nsEventListenerManager::RemoveEventListener(nsIDOMEventListener *aListener, if (deviceType && typeCount == 0) { DisableDevice(aType); + } else if (timeChangeEvent && typeCount == 0) { + DisableTimeChangeNotifications(); } } @@ -1109,3 +1115,27 @@ nsEventListenerManager::UnmarkGrayJSListeners() } } } + +void +nsEventListenerManager::EnableTimeChangeNotifications() +{ + nsCOMPtr window = do_QueryInterface(mTarget); + if (!window) { + return; + } + + NS_ASSERTION(window->IsInnerWindow(), "Target should not be an outer window"); + window->EnableTimeChangeNotifications(); +} + +void +nsEventListenerManager::DisableTimeChangeNotifications() +{ + nsCOMPtr window = do_QueryInterface(mTarget); + if (!window) { + return; + } + + NS_ASSERTION(window->IsInnerWindow(), "Target should not be an outer window"); + window->DisableTimeChangeNotifications(); +} diff --git a/content/events/src/nsEventListenerManager.h b/content/events/src/nsEventListenerManager.h index f77289920d96..4635b3be9bf8 100644 --- a/content/events/src/nsEventListenerManager.h +++ b/content/events/src/nsEventListenerManager.h @@ -261,6 +261,9 @@ protected: void EnableDevice(PRUint32 aType); void DisableDevice(PRUint32 aType); + void EnableTimeChangeNotifications(); + void DisableTimeChangeNotifications(); + public: /** * Set the "inline" event listener for aEventName to |v|. This diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index a8435f7ee0c7..a0c1ecd1393e 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -38,6 +38,7 @@ #include "Connection.h" #include "MobileConnection.h" #include "nsIIdleObserver.h" +#include "TimeManager.h" #ifdef MOZ_MEDIA_NAVIGATOR #include "MediaManager.h" @@ -115,6 +116,7 @@ NS_INTERFACE_MAP_BEGIN(Navigator) #endif NS_INTERFACE_MAP_ENTRY(nsIDOMNavigatorCamera) NS_INTERFACE_MAP_ENTRY(nsIDOMNavigatorSystemMessages) + NS_INTERFACE_MAP_ENTRY(nsIDOMMozNavigatorTime) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Navigator) NS_INTERFACE_MAP_END @@ -197,6 +199,9 @@ Navigator::Invalidate() } mDeviceStorageStores.Clear(); + if (mTimeManager) { + mTimeManager = nsnull; + } } nsPIDOMWindow * @@ -1241,21 +1246,9 @@ Navigator::GetMozMobileConnection(nsIDOMMozMobileConnection** aMobileConnection) if (!mMobileConnection) { nsCOMPtr window = do_QueryReferent(mWindow); - NS_ENSURE_TRUE(window && window->GetDocShell(), NS_OK); - - // Chrome is always allowed access, so do the permission check only - // for non-chrome pages. - if (!nsContentUtils::IsCallerChrome()) { - nsCOMPtr doc = do_QueryInterface(window->GetExtantDocument()); - NS_ENSURE_TRUE(doc, NS_OK); - - nsCOMPtr uri; - doc->NodePrincipal()->GetURI(getter_AddRefs(uri)); - - if (!nsContentUtils::URIIsChromeOrInPref(uri, "dom.mobileconnection.whitelist")) { - return NS_OK; - } - } + if (!CheckPermission("dom.mobileconnection.whitelist")) { + return NS_OK; + } mMobileConnection = new network::MobileConnection(); mMobileConnection->Init(window); @@ -1351,6 +1344,25 @@ Navigator::MozSetMessageHandler(const nsAString& aType, #endif } +//***************************************************************************** +// Navigator::nsIDOMNavigatorTime +//***************************************************************************** +NS_IMETHODIMP +Navigator::GetMozTime(nsIDOMMozTimeManager** aTime) +{ + if (!CheckPermission("dom.time.whitelist")) { + return NS_ERROR_DOM_SECURITY_ERR; + } + + if (!mTimeManager) { + *aTime = nsnull; + mTimeManager = new time::TimeManager(); + } + + NS_ADDREF(*aTime = mTimeManager); + return NS_OK; +} + //***************************************************************************** // nsNavigator::nsIDOMNavigatorCamera //***************************************************************************** @@ -1414,6 +1426,21 @@ Navigator::OnNavigation() } } +bool +Navigator::CheckPermission(const char* aPref) +{ + if (!nsContentUtils::IsCallerChrome()) { + nsCOMPtr win = do_QueryReferent(mWindow); + NS_ENSURE_TRUE(win, false); + nsCOMPtr doc = do_QueryInterface(win->GetExtantDocument()); + NS_ENSURE_TRUE(doc, false); + nsCOMPtr uri; + doc->NodePrincipal()->GetURI(getter_AddRefs(uri)); + return nsContentUtils::URIIsChromeOrInPref(uri, aPref); + } + + return true; +} } // namespace dom } // namespace mozilla diff --git a/dom/base/Navigator.h b/dom/base/Navigator.h index df12a3c021f0..a3c4a04ed16f 100644 --- a/dom/base/Navigator.h +++ b/dom/base/Navigator.h @@ -15,6 +15,7 @@ #include "nsINavigatorBattery.h" #include "nsIDOMNavigatorSms.h" #include "nsIDOMNavigatorNetwork.h" +#include "nsIDOMNavigatorTime.h" #include "nsAutoPtr.h" #include "nsWeakReference.h" #include "DeviceStorage.h" @@ -69,6 +70,10 @@ namespace power { class PowerManager; } // namespace power +namespace time { +class TimeManager; +} // namespace time + class Navigator : public nsIDOMNavigator , public nsIDOMClientInformation , public nsIDOMNavigatorDeviceStorage @@ -88,6 +93,7 @@ class Navigator : public nsIDOMNavigator #endif , public nsIDOMNavigatorCamera , public nsIDOMNavigatorSystemMessages + , public nsIDOMMozNavigatorTime { public: Navigator(nsPIDOMWindow *aInnerWindow); @@ -113,6 +119,7 @@ public: NS_DECL_NSIDOMNAVIGATORBLUETOOTH #endif NS_DECL_NSIDOMNAVIGATORSYSTEMMESSAGES + NS_DECL_NSIDOMMOZNAVIGATORTIME static void Init(); @@ -144,6 +151,7 @@ public: private: bool IsSmsAllowed() const; bool IsSmsSupported() const; + bool CheckPermission(const char* aPref); nsRefPtr mMimeTypes; nsRefPtr mPlugins; @@ -164,6 +172,7 @@ private: nsRefPtr mCameraManager; nsCOMPtr mMessagesManager; nsTArray > mDeviceStorageStores; + nsRefPtr mTimeManager; nsWeakPtr mWindow; }; diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index c2b05fdb4d40..d66e10792918 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -523,6 +523,7 @@ using mozilla::dom::indexedDB::IDBWrapperCache; #include "nsIDOMNavigatorSystemMessages.h" #include "mozilla/dom/Activity.h" +#include "TimeManager.h" #include "DOMCameraManager.h" #include "CameraControl.h" @@ -1698,6 +1699,9 @@ static nsDOMClassInfoData sClassInfoData[] = { EVENTTARGET_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(MozActivity, nsEventTargetSH, EVENTTARGET_SCRIPTABLE_FLAGS) + + NS_DEFINE_CLASSINFO_DATA(MozTimeManager, nsDOMGenericSH, + DOM_DEFAULT_SCRIPTABLE_FLAGS) }; // Objects that should be constructable through |new Name();| @@ -2471,6 +2475,7 @@ nsDOMClassInfo::Init() #endif DOM_CLASSINFO_MAP_ENTRY(nsIDOMNavigatorCamera) DOM_CLASSINFO_MAP_ENTRY(nsIDOMNavigatorSystemMessages) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozNavigatorTime) DOM_CLASSINFO_MAP_END @@ -4506,6 +4511,10 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget) DOM_CLASSINFO_MAP_END + DOM_CLASSINFO_MAP_BEGIN(MozTimeManager, nsIDOMMozTimeManager) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozTimeManager) + DOM_CLASSINFO_MAP_END + #ifdef DEBUG { PRUint32 i = ArrayLength(sClassInfoData); diff --git a/dom/base/nsDOMClassInfoClasses.h b/dom/base/nsDOMClassInfoClasses.h index c587c2c12e76..9e857f22bad9 100644 --- a/dom/base/nsDOMClassInfoClasses.h +++ b/dom/base/nsDOMClassInfoClasses.h @@ -538,3 +538,5 @@ DOMCI_CLASS(FileRequest) DOMCI_CLASS(LockedFile) DOMCI_CLASS(MozActivity) + +DOMCI_CLASS(MozTimeManager) diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 8eb091e4bd40..017707faf788 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -222,6 +222,7 @@ #include "nsDOMEventTargetHelper.h" #include "nsIAppsService.h" #include "prrng.h" +#include "TimeChangeObserver.h" #ifdef ANDROID #include @@ -1055,6 +1056,7 @@ nsGlobalWindow::CleanUp(bool aIgnoreModalDialog) mIdleTimer = nullptr; } + DisableTimeChangeNotifications(); #ifdef DEBUG nsCycleCollector_DEBUG_shouldBeFreed(static_cast(this)); #endif @@ -10620,6 +10622,18 @@ nsGlobalWindow::GetURL(nsIDOMMozURLProperty** aURL) return NS_OK; } +void +nsGlobalWindow::EnableTimeChangeNotifications() +{ + nsSystemTimeChangeObserver::GetInstance()->AddWindowListener(this); +} + +void +nsGlobalWindow::DisableTimeChangeNotifications() +{ + nsSystemTimeChangeObserver::GetInstance()->RemoveWindowListener(this); +} + // static bool nsGlobalWindow::HasIndexedDBSupport() diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index 39c1deb1c95e..ad3b93b4e077 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -537,6 +537,9 @@ public: virtual void EnableDeviceSensor(PRUint32 aType); virtual void DisableDeviceSensor(PRUint32 aType); + virtual void EnableTimeChangeNotifications(); + virtual void DisableTimeChangeNotifications(); + virtual nsresult SetArguments(nsIArray *aArguments, nsIPrincipal *aOrigin); static bool DOMWindowDumpEnabled(); diff --git a/dom/base/nsPIDOMWindow.h b/dom/base/nsPIDOMWindow.h index 1d40ebfba0b3..0bebde124f97 100644 --- a/dom/base/nsPIDOMWindow.h +++ b/dom/base/nsPIDOMWindow.h @@ -576,6 +576,9 @@ public: */ virtual void DisableDeviceSensor(PRUint32 aType) = 0; + virtual void EnableTimeChangeNotifications() = 0; + virtual void DisableTimeChangeNotifications() = 0; + /** * Set a arguments for this window. This will be set on the window * right away (if there's an existing document) and it will also be diff --git a/dom/time/Makefile.in b/dom/time/Makefile.in index 0d037c447877..63efec4b5bdc 100644 --- a/dom/time/Makefile.in +++ b/dom/time/Makefile.in @@ -16,7 +16,14 @@ FORCE_STATIC_LIB = 1 include $(topsrcdir)/dom/dom-config.mk -CPPSRCS = $(NULL) +CPPSRCS = \ + TimeManager.cpp \ + TimeChangeObserver.cpp \ + $(NULL) + +EXPORTS = \ + TimeChangeObserver.h \ + $(NULL) XPIDLSRCS = \ nsIDOMNavigatorTime.idl \ @@ -24,4 +31,5 @@ XPIDLSRCS = \ $(NULL) include $(topsrcdir)/config/config.mk +include $(topsrcdir)/ipc/chromium/chromium-config.mk include $(topsrcdir)/config/rules.mk diff --git a/dom/time/TimeChangeObserver.cpp b/dom/time/TimeChangeObserver.cpp new file mode 100644 index 000000000000..1474fc25197a --- /dev/null +++ b/dom/time/TimeChangeObserver.cpp @@ -0,0 +1,87 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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/. */ + +#include "TimeChangeObserver.h" +#include "mozilla/ClearOnShutdown.h" +#include "mozilla/StaticPtr.h" +#include "nsPIDOMWindow.h" +#include "nsDOMEvent.h" +#include "nsContentUtils.h" + +using namespace mozilla::hal; +using namespace mozilla; + +StaticAutoPtr sObserver; + +nsSystemTimeChangeObserver* nsSystemTimeChangeObserver::GetInstance() +{ + if (!sObserver) { + sObserver = new nsSystemTimeChangeObserver(); + ClearOnShutdown(&sObserver); + } + return sObserver; +} + +void +nsSystemTimeChangeObserver::Notify(const SystemTimeChange& aReason) +{ + //Copy mWindowListeners and iterate over windowListeners instead because + //mWindowListeners may be modified while we loop. + nsTArray windowListeners; + for (PRUint32 i = 0; i < mWindowListeners.Length(); i++) { + windowListeners.AppendElement(mWindowListeners.SafeElementAt(i)); + } + + for (PRInt32 i = windowListeners.Length() - 1; i >= 0; i--) { + nsCOMPtr window = do_QueryReferent(windowListeners[i]); + if (!window) { + mWindowListeners.RemoveElement(windowListeners[i]); + return; + } + + nsCOMPtr domdoc; + window->GetDocument(getter_AddRefs(domdoc)); + nsCOMPtr doc(do_QueryInterface(domdoc)); + if (!domdoc) { + return; + } + + nsContentUtils::DispatchTrustedEvent(doc, window, + NS_LITERAL_STRING("moztimechange"), /* bubbles = */ true, + /* canceable = */ false); + } +} + +nsresult +nsSystemTimeChangeObserver::AddWindowListener(nsIDOMWindow* aWindow) +{ + if (!aWindow) { + return NS_ERROR_ILLEGAL_VALUE; + } + + if (mWindowListeners.IndexOf(NS_GetWeakReference(aWindow)) != + nsTArray::NoIndex) { + return NS_OK; + } + + if (mWindowListeners.Length() == 0) { + RegisterSystemTimeChangeObserver(this); + } + + mWindowListeners.AppendElement(NS_GetWeakReference(aWindow)); + return NS_OK; +} + +nsresult +nsSystemTimeChangeObserver::RemoveWindowListener(nsIDOMWindow *aWindow) +{ + mWindowListeners.RemoveElement(NS_GetWeakReference(aWindow)); + + if (mWindowListeners.Length() == 0) { + UnregisterSystemTimeChangeObserver(this); + } + + return NS_OK; +} diff --git a/dom/time/TimeChangeObserver.h b/dom/time/TimeChangeObserver.h new file mode 100644 index 000000000000..2b7c8efe1e2d --- /dev/null +++ b/dom/time/TimeChangeObserver.h @@ -0,0 +1,29 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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/. */ + +#ifndef _mozilla_time_change_observer_h_ +#define _mozilla_time_change_observer_h_ + +#include "mozilla/Hal.h" +#include "mozilla/Observer.h" +#include "mozilla/HalTypes.h" +#include "nsPIDOMWindow.h" +#include "nsWeakPtr.h" + +typedef mozilla::Observer SystemTimeChangeObserver; + +class nsSystemTimeChangeObserver : public SystemTimeChangeObserver +{ +public: + static nsSystemTimeChangeObserver* GetInstance(); + void Notify(const mozilla::hal::SystemTimeChange& aReason); + nsresult AddWindowListener(nsIDOMWindow *aWindow); + nsresult RemoveWindowListener(nsIDOMWindow *aWindow); +private: + nsSystemTimeChangeObserver() {}; + nsTArray mWindowListeners; +}; + +#endif //_mozilla_time_change_observer_h_ diff --git a/dom/time/TimeManager.cpp b/dom/time/TimeManager.cpp new file mode 100644 index 000000000000..227cd813b37b --- /dev/null +++ b/dom/time/TimeManager.cpp @@ -0,0 +1,57 @@ +/* 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/. */ +#include "jsapi.h" +#include "mozilla/Hal.h" +#include "nsDOMEvent.h" +#include "nsDOMEventTargetHelper.h" +#include "nsIDOMClassInfo.h" +#include "prtime.h" +#include "TimeManager.h" + +using namespace mozilla::hal; + +DOMCI_DATA(MozTimeManager, mozilla::dom::time::TimeManager) + +namespace mozilla { +namespace dom { +namespace time { + +NS_INTERFACE_MAP_BEGIN(TimeManager) + NS_INTERFACE_MAP_ENTRY(nsIDOMMozTimeManager) + NS_INTERFACE_MAP_ENTRY(nsISupports) + NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozTimeManager) +NS_INTERFACE_MAP_END + +NS_IMPL_ADDREF(TimeManager) +NS_IMPL_RELEASE(TimeManager) + +nsresult +TimeManager::Set(const JS::Value& date, JSContext* ctx) { + double nowMSec = JS_Now() / 1000; + double dateMSec; + + if (date.isObject()) { + JSObject* dateObj = JSVAL_TO_OBJECT(date); + + if (JS_ObjectIsDate(ctx, dateObj) && js_DateIsValid(ctx, dateObj)) { + dateMSec = js_DateGetMsecSinceEpoch(ctx, dateObj); + } + else { + NS_WARN_IF_FALSE(JS_ObjectIsDate(ctx, dateObj), "This is not a Date object"); + NS_WARN_IF_FALSE(js_DateIsValid(ctx, dateObj), "Date is not valid"); + return NS_ERROR_INVALID_ARG; + } + } else if (date.isNumber()) { + dateMSec = date.toNumber(); + } else { + return NS_ERROR_INVALID_ARG; + } + + hal::AdjustSystemClock(JS_DoubleToInt32(dateMSec - nowMSec)); + return NS_OK; +} + +} // namespace time +} // namespace dom +} // namespace mozilla diff --git a/dom/time/TimeManager.h b/dom/time/TimeManager.h new file mode 100644 index 000000000000..8121bbde5bcd --- /dev/null +++ b/dom/time/TimeManager.h @@ -0,0 +1,31 @@ +/* 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/. */ + +#ifndef mozilla_dom_time_TimeManager_h +#define mozilla_dom_time_TimeManager_h + +#include "mozilla/HalTypes.h" +#include "nsIDOMTimeManager.h" +#include "mozilla/Observer.h" + +class nsPIDOMWindow; + +namespace mozilla { + +typedef Observer SystemTimeObserver; + +namespace dom { +namespace time { +class TimeManager : public nsIDOMMozTimeManager +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIDOMMOZTIMEMANAGER +}; + +} // namespace time +} // namespace dom +} // namespace mozilla + +#endif //mozilla_dom_time_TimeManager_h diff --git a/dom/time/nsIDOMTimeManager.idl b/dom/time/nsIDOMTimeManager.idl index fd5138fb2c5b..af2f7eceaf46 100644 --- a/dom/time/nsIDOMTimeManager.idl +++ b/dom/time/nsIDOMTimeManager.idl @@ -7,6 +7,14 @@ [scriptable, builtinclass, uuid(d29beaaa-bd54-4fd5-9f18-e0eedb1dc96d)] interface nsIDOMMozTimeManager : nsISupports { - // jsval could be Date object or UTC seconds + /* Set the system time. + * + * The |time| argument can be either a Date object or a number. + * + * - If |time| is a number, it's interpreted as seconds since the epoch + * (midnight UTC on January 1, 1970) + * - If |time| is a Date object, |set(time)| is equivalent to + * |set(time.getTime())|. + */ [implicit_jscontext] void set(in jsval time); }; diff --git a/layout/build/Makefile.in b/layout/build/Makefile.in index 5586bf1fd3cd..50d48134dc94 100644 --- a/layout/build/Makefile.in +++ b/layout/build/Makefile.in @@ -83,6 +83,7 @@ SHARED_LIBRARY_LIBS = \ $(DEPTH)/dom/indexedDB/$(LIB_PREFIX)dom_indexeddb_s.$(LIB_SUFFIX) \ $(DEPTH)/dom/indexedDB/ipc/$(LIB_PREFIX)dom_indexeddb_ipc_s.$(LIB_SUFFIX) \ $(DEPTH)/dom/browser-element/$(LIB_PREFIX)dom_browserelement_s.$(LIB_SUFFIX) \ + $(DEPTH)/dom/time/$(LIB_PREFIX)dom_time_s.$(LIB_SUFFIX) \ $(DEPTH)/editor/libeditor/text/$(LIB_PREFIX)texteditor_s.$(LIB_SUFFIX) \ $(DEPTH)/editor/libeditor/base/$(LIB_PREFIX)editorbase_s.$(LIB_SUFFIX) \ $(DEPTH)/parser/html/$(LIB_PREFIX)html5p_s.$(LIB_SUFFIX) \ diff --git a/widget/nsGUIEvent.h b/widget/nsGUIEvent.h index 1b323e3208d7..e772b5625037 100644 --- a/widget/nsGUIEvent.h +++ b/widget/nsGUIEvent.h @@ -537,6 +537,9 @@ class nsHashKey; #define NS_POINTERLOCKCHANGE (NS_POINTERLOCK_START) #define NS_POINTERLOCKERROR (NS_POINTERLOCK_START + 1) +//System time is changed +#define NS_MOZ_TIME_CHANGE_EVENT 5400 + /** * Return status for event processors, nsEventStatus, is defined in * nsEvent.h. From e9b9fa897003309bbace706757d8e7c3b9c29e1d Mon Sep 17 00:00:00 2001 From: Phil Ringnalda Date: Tue, 7 Aug 2012 21:26:41 -0700 Subject: [PATCH 122/169] Backout e662aa8c9389 (Bug 780604), 3979c98e3e9a:5ccb28fc0bee (Bug 780498) for Windows orange --- .../components/osfile/osfile_unix_front.jsm | 85 +++++++++++-------- toolkit/components/osfile/osfile_win_back.jsm | 11 ++- .../tests/mochi/worker_test_osfile_front.js | 11 +-- 3 files changed, 62 insertions(+), 45 deletions(-) diff --git a/toolkit/components/osfile/osfile_unix_front.jsm b/toolkit/components/osfile/osfile_unix_front.jsm index 85e12e0206da..33feb6da2270 100644 --- a/toolkit/components/osfile/osfile_unix_front.jsm +++ b/toolkit/components/osfile/osfile_unix_front.jsm @@ -335,6 +335,22 @@ UnixFile.copyfile(sourcePath, destPath, null, flags) ); }; + + // This implementation uses |copyfile(3)|, from the BSD library. + // Adding moving of hierarchies and/or attributes is just a flag + // away. + File.move = function movefile(sourcePath, destPath, options) { + // This implementation uses |copyfile(3)|, from the BSD library. + // It can move directory hierarchies. + options = options || noOptions; + let flags = Const.COPYFILE_DATA | Const.COPYFILE_MOVE; + if (options.noOverwrite) { + flags |= Const.COPYFILE_EXCL; + } + throw_on_negative("move", + UnixFile.copyfile(sourcePath, destPath, null, flags) + ); + }; } else { // If the OS does not implement file copying for us, we need to // implement it ourselves. For this purpose, we need to define @@ -458,37 +474,36 @@ pipe_write.dispose(); } }; - } else { - // Fallback implementation of pump for other Unix platforms. - pump = pump_userland; - } + } else { + // Fallback implementation of pump for other Unix platforms. + pump = pump_userland; + } - // Implement |copy| using |pump|. - // This implementation would require some work before being able to - // copy directories - File.copy = function copy(sourcePath, destPath, options) { - options = options || noOptions; - let source, dest; - let result; - try { - source = File.open(sourcePath); - if (options.noOverwrite) { - dest = File.open(destPath, {create:true}); - } else { - dest = File.open(destPath, {write:true}); - } - result = pump(source, dest, options); - } catch (x) { - if (dest) { - dest.close(); - } - if (source) { - source.close(); - } - throw x; + // Implement |copy| using |pump|. + // This implementation would require some work before being able to + // copy directories + File.copy = function copy(sourcePath, destPath, options) { + options = options || noOptions; + let source, dest; + let result; + try { + source = File.open(sourcePath); + if (options.noOverwrite) { + dest = File.open(destPath, {create:true}); + } else { + dest = File.open(destPath, {write:true}); } - }; - } // End of definition of copy + result = pump(source, dest, options); + } catch (x) { + if (dest) { + dest.close(); + } + if (source) { + source.close(); + } + throw x; + } + }; // Implement |move| using |rename| (wherever possible) or |copy| // (if files are on distinct devices). @@ -524,11 +539,13 @@ throw new File.Error(); } - // Otherwise, copy and remove. - File.copy(sourcePath, destPath, options); - // FIXME: Clean-up in case of copy error? - File.remove(sourcePath); - }; + // Otherwise, copy and remove. + File.copy(sourcePath, destPath, options); + // FIXME: Clean-up in case of copy error? + File.remove(sourcePath); + }; + + } // End of definition of copy/move /** * Iterate on one directory. diff --git a/toolkit/components/osfile/osfile_win_back.jsm b/toolkit/components/osfile/osfile_win_back.jsm index 5431470c0716..bfc0a70f0f98 100644 --- a/toolkit/components/osfile/osfile_win_back.jsm +++ b/toolkit/components/osfile/osfile_win_back.jsm @@ -81,7 +81,16 @@ * a file descriptor in case of success. */ Types.maybe_HANDLE = - Types.maybe_HANDLE.withName("maybe_find_HANDLE"); + new Type("maybe_HANDLE", + Types.HANDLE.implementation, + function (maybe) { + if (ctypes.cast(maybe, ctypes.int).value == invalid_handle) { + // Ensure that API clients can effectively compare against + // Const.INVALID_HANDLE_VALUE. Without this cast, + // == would always return |false|. + return invalid_handle; + } + return ctypes.CDataFinalizer(maybe, _CloseHandle); }); /** diff --git a/toolkit/components/osfile/tests/mochi/worker_test_osfile_front.js b/toolkit/components/osfile/tests/mochi/worker_test_osfile_front.js index b66925a16361..ce93834b39ae 100644 --- a/toolkit/components/osfile/tests/mochi/worker_test_osfile_front.js +++ b/toolkit/components/osfile/tests/mochi/worker_test_osfile_front.js @@ -192,18 +192,9 @@ function test_move_file() ok(true, "test_move_file: Move complete"); - // 3. Check that destination exists + // 3. Check compare_files("test_move_file", src_file_name, tmp2_file_name); - // 4. Check that original file does not exist anymore - let exn; - try { - OS.File.open(tmp_file_name); - } catch (x) { - exn = x; - } - ok(!!exn, "test_move_file: Original file has been removed"); - ok(true, "test_move_file: Cleaning up"); OS.File.remove(tmp2_file_name); } From 40042587bb8a2591b96b8084671c24f508f699e9 Mon Sep 17 00:00:00 2001 From: Jan Varga Date: Wed, 8 Aug 2012 06:35:48 +0200 Subject: [PATCH 123/169] Bug 780625 - Followup fix for "Don't install quota handlers on chrome databases". r=bent --- dom/indexedDB/FileManager.cpp | 9 ++++++--- dom/indexedDB/FileManager.h | 3 ++- dom/indexedDB/IndexedDatabaseManager.cpp | 8 ++++---- dom/indexedDB/OpenDatabaseHelper.cpp | 2 +- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/dom/indexedDB/FileManager.cpp b/dom/indexedDB/FileManager.cpp index d57088bf3cfa..5c151341c1aa 100644 --- a/dom/indexedDB/FileManager.cpp +++ b/dom/indexedDB/FileManager.cpp @@ -41,7 +41,8 @@ EnumerateToTArray(const PRUint64& aKey, nsresult FileManager::Init(nsIFile* aDirectory, - mozIStorageConnection* aConnection) + mozIStorageConnection* aConnection, + FactoryPrivilege aPrivilege) { NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!"); @@ -103,8 +104,10 @@ FileManager::Init(nsIFile* aDirectory, NS_ENSURE_SUCCESS(rv, rv); if (flag) { - rv = ss->UpdateQuotaInformationForFile(file); - NS_ENSURE_SUCCESS(rv, rv); + if (aPrivilege != Chrome) { + rv = ss->UpdateQuotaInformationForFile(file); + NS_ENSURE_SUCCESS(rv, rv); + } } else { rv = file->Remove(false); diff --git a/dom/indexedDB/FileManager.h b/dom/indexedDB/FileManager.h index 0aef58529410..4a2eafad3ca2 100644 --- a/dom/indexedDB/FileManager.h +++ b/dom/indexedDB/FileManager.h @@ -60,7 +60,8 @@ public: } nsresult Init(nsIFile* aDirectory, - mozIStorageConnection* aConnection); + mozIStorageConnection* aConnection, + FactoryPrivilege aPrivilege); nsresult Load(mozIStorageConnection* aConnection); diff --git a/dom/indexedDB/IndexedDatabaseManager.cpp b/dom/indexedDB/IndexedDatabaseManager.cpp index ccd1c051c22e..28e04b110865 100644 --- a/dom/indexedDB/IndexedDatabaseManager.cpp +++ b/dom/indexedDB/IndexedDatabaseManager.cpp @@ -733,7 +733,7 @@ IndexedDatabaseManager::GetIndexedDBQuotaMB() nsresult IndexedDatabaseManager::EnsureOriginIsInitialized(const nsACString& aOrigin, - FactoryPrivilege mPrivilege, + FactoryPrivilege aPrivilege, nsIFile** aDirectory) { #ifdef DEBUG @@ -786,7 +786,7 @@ IndexedDatabaseManager::EnsureOriginIsInitialized(const nsACString& aOrigin, do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID); NS_ENSURE_TRUE(ss, NS_ERROR_FAILURE); - if (mPrivilege != Chrome) { + if (aPrivilege != Chrome) { rv = ss->SetQuotaForFilenamePattern(pattern, GetIndexedDBQuotaMB() * 1024 * 1024, mQuotaCallbackSingleton, nsnull); @@ -878,12 +878,12 @@ IndexedDatabaseManager::EnsureOriginIsInitialized(const nsACString& aOrigin, nsRefPtr fileManager = new FileManager(aOrigin, databaseName); - rv = fileManager->Init(fileManagerDirectory, connection); + rv = fileManager->Init(fileManagerDirectory, connection, aPrivilege); NS_ENSURE_SUCCESS(rv, rv); fileManagers->AppendElement(fileManager); - if (mPrivilege != Chrome) { + if (aPrivilege != Chrome) { rv = ss->UpdateQuotaInformationForFile(file); NS_ENSURE_SUCCESS(rv, rv); } diff --git a/dom/indexedDB/OpenDatabaseHelper.cpp b/dom/indexedDB/OpenDatabaseHelper.cpp index 0ee9b0482c35..5e9f1bf05f45 100644 --- a/dom/indexedDB/OpenDatabaseHelper.cpp +++ b/dom/indexedDB/OpenDatabaseHelper.cpp @@ -1691,7 +1691,7 @@ OpenDatabaseHelper::DoDatabaseWork() NS_ENSURE_TRUE(mFileManager, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); if (!mFileManager->Inited()) { - rv = mFileManager->Init(fileManagerDirectory, connection); + rv = mFileManager->Init(fileManagerDirectory, connection, mPrivilege); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); } From 95ec692466cacf4a5408cf89828233fc8cfd57d5 Mon Sep 17 00:00:00 2001 From: Simon Montagu Date: Tue, 17 Apr 2012 07:01:29 +0300 Subject: [PATCH 124/169] Tests for dir(ltr/rtl) CSS selector. bug 562169, r=bz --- content/base/test/Makefile.in | 2 ++ content/base/test/test_bug562169-1.html | 44 +++++++++++++++++++++++ content/base/test/test_bug562169-2.html | 29 ++++++++++++++++ layout/reftests/bidi/562169-1-ref.html | 31 +++++++++++++++++ layout/reftests/bidi/562169-1.html | 32 +++++++++++++++++ layout/reftests/bidi/562169-1a.html | 46 +++++++++++++++++++++++++ layout/reftests/bidi/562169-2-ref.html | 29 ++++++++++++++++ layout/reftests/bidi/562169-2.html | 30 ++++++++++++++++ layout/reftests/bidi/562169-2a.html | 36 +++++++++++++++++++ layout/reftests/bidi/562169-3-ref.html | 16 +++++++++ layout/reftests/bidi/562169-3.html | 15 ++++++++ layout/reftests/bidi/562169-3a.html | 26 ++++++++++++++ layout/reftests/bidi/562169-4-ref.html | 16 +++++++++ layout/reftests/bidi/562169-4.html | 29 ++++++++++++++++ layout/reftests/bidi/reftest.list | 7 ++++ 15 files changed, 388 insertions(+) create mode 100644 content/base/test/test_bug562169-1.html create mode 100644 content/base/test/test_bug562169-2.html create mode 100644 layout/reftests/bidi/562169-1-ref.html create mode 100644 layout/reftests/bidi/562169-1.html create mode 100644 layout/reftests/bidi/562169-1a.html create mode 100644 layout/reftests/bidi/562169-2-ref.html create mode 100644 layout/reftests/bidi/562169-2.html create mode 100644 layout/reftests/bidi/562169-2a.html create mode 100644 layout/reftests/bidi/562169-3-ref.html create mode 100644 layout/reftests/bidi/562169-3.html create mode 100644 layout/reftests/bidi/562169-3a.html create mode 100644 layout/reftests/bidi/562169-4-ref.html create mode 100644 layout/reftests/bidi/562169-4.html diff --git a/content/base/test/Makefile.in b/content/base/test/Makefile.in index a73aa0f5fedc..6e22e1b82727 100644 --- a/content/base/test/Makefile.in +++ b/content/base/test/Makefile.in @@ -381,6 +381,8 @@ MOCHITEST_FILES_B = \ test_bug562652.html \ test_bug562137.html \ file_bug562137.txt \ + test_bug562169-1.html \ + test_bug562169-2.html \ test_bug548193.html \ file_bug548193.sjs \ test_html_colors_quirks.html \ diff --git a/content/base/test/test_bug562169-1.html b/content/base/test/test_bug562169-1.html new file mode 100644 index 000000000000..e2e9e9da2800 --- /dev/null +++ b/content/base/test/test_bug562169-1.html @@ -0,0 +1,44 @@ + + + + + + Test for Bug 562169 + + + + +Mozilla Bug 562169 +

    + +
    +
    +
    + + diff --git a/content/base/test/test_bug562169-2.html b/content/base/test/test_bug562169-2.html new file mode 100644 index 000000000000..b49eed016fb9 --- /dev/null +++ b/content/base/test/test_bug562169-2.html @@ -0,0 +1,29 @@ + + + + + + Test for Bug 562169 + + + + +Mozilla Bug 562169 +

    + +
    +
    +
    + + diff --git a/layout/reftests/bidi/562169-1-ref.html b/layout/reftests/bidi/562169-1-ref.html new file mode 100644 index 000000000000..8aded4f766d6 --- /dev/null +++ b/layout/reftests/bidi/562169-1-ref.html @@ -0,0 +1,31 @@ + + + + + dir() selector + + + +
    This element has default direction.
    +
    This element is ltr.
    +
    This element is rtl.
    +
    +
    This element should inherit ltr.
    +
    This element is ltr.
    +
    This element is rtl.
    +
    Every word in this element should inherit ltr.
    +
    +
    +
    This element should inherit rtl.
    +
    This element is ltr.
    +
    This element is rtl.
    +
    Every word in this element should inherit rtl.
    +
    +
    This element has an invalid dir attribute and + should have default direction.
    + + diff --git a/layout/reftests/bidi/562169-1.html b/layout/reftests/bidi/562169-1.html new file mode 100644 index 000000000000..d6cfe554f802 --- /dev/null +++ b/layout/reftests/bidi/562169-1.html @@ -0,0 +1,32 @@ + + + + + dir() selector + + + +
    This element has default direction.
    +
    This element is ltr.
    +
    This element is rtl.
    +
    +
    This element should inherit ltr.
    +
    This element is ltr.
    +
    This element is rtl.
    +
    Every word in this element should inherit ltr.
    +
    +
    +
    This element should inherit rtl.
    +
    This element is ltr.
    +
    This element is rtl.
    +
    Every word in this element should inherit rtl.
    +
    +
    This element has an invalid dir attribute and + should have default direction.
    + + diff --git a/layout/reftests/bidi/562169-1a.html b/layout/reftests/bidi/562169-1a.html new file mode 100644 index 000000000000..f6102951fd33 --- /dev/null +++ b/layout/reftests/bidi/562169-1a.html @@ -0,0 +1,46 @@ + + + + + dir() selector + + + + +
    This element has default direction.
    +
    This element is ltr.
    +
    This element is rtl.
    +
    +
    This element should inherit ltr.
    +
    This element is ltr.
    +
    This element is rtl.
    +
    Every word in this element should inherit ltr.
    +
    +
    +
    This element should inherit rtl.
    +
    This element is ltr.
    +
    This element is rtl.
    +
    Every word in this element should inherit rtl.
    +
    +
    This element has an invalid dir attribute and + should have default direction.
    + + diff --git a/layout/reftests/bidi/562169-2-ref.html b/layout/reftests/bidi/562169-2-ref.html new file mode 100644 index 000000000000..0acc957b180f --- /dev/null +++ b/layout/reftests/bidi/562169-2-ref.html @@ -0,0 +1,29 @@ + + + + + dir() selector + + + +
    This element has default direction.
    +
    This element is ltr.
    +
    This element is rtl.
    +
    +
    This element should inherit ltr.
    +
    This element is ltr.
    +
    This element is rtl.
    +
    +
    +
    This element should inherit rtl.
    +
    This element is ltr.
    +
    This element is rtl.
    +
    +
    This element has an invalid dir attribute and + should have default direction.
    + + diff --git a/layout/reftests/bidi/562169-2.html b/layout/reftests/bidi/562169-2.html new file mode 100644 index 000000000000..cea59a3fe029 --- /dev/null +++ b/layout/reftests/bidi/562169-2.html @@ -0,0 +1,30 @@ + + + + + dir() selector + + + +
    This element has default direction.
    +
    This element is ltr.
    +
    This element is rtl.
    +
    +
    This element should inherit ltr.
    +
    This element is ltr.
    +
    This element is rtl.
    +
    +
    +
    This element should inherit rtl.
    +
    This element is ltr.
    +
    This element is rtl.
    +
    +
    This element has an invalid dir attribute and + should have default direction.
    + + diff --git a/layout/reftests/bidi/562169-2a.html b/layout/reftests/bidi/562169-2a.html new file mode 100644 index 000000000000..3f8044fd0310 --- /dev/null +++ b/layout/reftests/bidi/562169-2a.html @@ -0,0 +1,36 @@ + + + + + dir() selector + + + + +
    This element has default direction.
    +
    This element is ltr.
    +
    This element is rtl.
    +
    +
    This element should inherit ltr.
    +
    This element is ltr.
    +
    This element is rtl.
    +
    +
    +
    This element should inherit rtl.
    +
    This element is ltr.
    +
    This element is rtl.
    +
    +
    This element has an invalid dir attribute and + should have default direction.
    + + diff --git a/layout/reftests/bidi/562169-3-ref.html b/layout/reftests/bidi/562169-3-ref.html new file mode 100644 index 000000000000..ea848f61a16f --- /dev/null +++ b/layout/reftests/bidi/562169-3-ref.html @@ -0,0 +1,16 @@ + + + + + dir() selector + + + +
    This element is rtl.
    +
    This element has default direction.
    + + diff --git a/layout/reftests/bidi/562169-3.html b/layout/reftests/bidi/562169-3.html new file mode 100644 index 000000000000..422e60827668 --- /dev/null +++ b/layout/reftests/bidi/562169-3.html @@ -0,0 +1,15 @@ + + + + + dir() selector + + + +
    This element is rtl.
    +
    This element has default direction.
    + + diff --git a/layout/reftests/bidi/562169-3a.html b/layout/reftests/bidi/562169-3a.html new file mode 100644 index 000000000000..9df28794a558 --- /dev/null +++ b/layout/reftests/bidi/562169-3a.html @@ -0,0 +1,26 @@ + + + + + dir() selector + + + + +
    This element is rtl.
    +
    This element has default direction.
    + + diff --git a/layout/reftests/bidi/562169-4-ref.html b/layout/reftests/bidi/562169-4-ref.html new file mode 100644 index 000000000000..b5cdada97b6d --- /dev/null +++ b/layout/reftests/bidi/562169-4-ref.html @@ -0,0 +1,16 @@ + + + + + dir() selector + + + +
    This element is rtl. This span should + inherit rtl from the parent. This span should inherit rtl + from the grandparent.
    + + diff --git a/layout/reftests/bidi/562169-4.html b/layout/reftests/bidi/562169-4.html new file mode 100644 index 000000000000..56075adc2ba8 --- /dev/null +++ b/layout/reftests/bidi/562169-4.html @@ -0,0 +1,29 @@ + + + + + dir() selector + + + + +
    This element is rtl.
    + + diff --git a/layout/reftests/bidi/reftest.list b/layout/reftests/bidi/reftest.list index ab4035ba825e..fcb831c9480b 100644 --- a/layout/reftests/bidi/reftest.list +++ b/layout/reftests/bidi/reftest.list @@ -86,6 +86,13 @@ random-if(winWidget) == 305643-1.html 305643-1-ref.html # depends on windows ver == 503957-1.html 503957-1-ref.html == 525740-1.html 525740-1-ref.html == 536963-1.html 536963-1-ref.html +== 562169-1.html 562169-1-ref.html +== 562169-1a.html 562169-1-ref.html +== 562169-2.html 562169-2-ref.html +== 562169-2a.html 562169-2-ref.html +== 562169-3.html 562169-3-ref.html +== 562169-3a.html 562169-3-ref.html +== 562169-4.html 562169-4-ref.html == 588739-1.html 588739-ref.html == 588739-2.html 588739-ref.html == 588739-3.html 588739-ref.html From aed3f621eb9da4decf39cdfe3eece3179c28fc3a Mon Sep 17 00:00:00 2001 From: Simon Montagu Date: Tue, 7 Aug 2012 21:44:24 -0700 Subject: [PATCH 125/169] Add support for :dir(ltr/rtl) CSS selector, layout/style part. Bug 562159, r=bz --- content/events/public/nsEventStates.h | 4 ++ .../html/content/src/nsGenericHTMLElement.h | 1 + .../en-US/chrome/layout/css.properties | 1 + layout/style/nsCSSParser.cpp | 6 +- layout/style/nsCSSPseudoClassList.h | 50 +++++++++++---- layout/style/nsCSSPseudoClasses.cpp | 3 +- layout/style/nsCSSRuleProcessor.cpp | 62 ++++++++++++++++--- 7 files changed, 105 insertions(+), 22 deletions(-) diff --git a/content/events/public/nsEventStates.h b/content/events/public/nsEventStates.h index ff36910a30d2..0a448df69a25 100644 --- a/content/events/public/nsEventStates.h +++ b/content/events/public/nsEventStates.h @@ -248,6 +248,10 @@ private: #define NS_EVENT_STATE_VULNERABLE_NO_UPDATE NS_DEFINE_EVENT_STATE_MACRO(41) // Platform does not support plugin content (some mobile platforms) #define NS_EVENT_STATE_TYPE_UNSUPPORTED_PLATFORM NS_DEFINE_EVENT_STATE_MACRO(42) +// Element is ltr (for :dir pseudo-class) +#define NS_EVENT_STATE_LTR NS_DEFINE_EVENT_STATE_MACRO(43) +// Element is rtl (for :dir pseudo-class) +#define NS_EVENT_STATE_RTL NS_DEFINE_EVENT_STATE_MACRO(44) /** * NOTE: do not go over 63 without updating nsEventStates::InternalType! diff --git a/content/html/content/src/nsGenericHTMLElement.h b/content/html/content/src/nsGenericHTMLElement.h index 4cd54732ab75..b1e04ea37824 100644 --- a/content/html/content/src/nsGenericHTMLElement.h +++ b/content/html/content/src/nsGenericHTMLElement.h @@ -49,6 +49,7 @@ public: { NS_ASSERTION(mNodeInfo->NamespaceID() == kNameSpaceID_XHTML, "Unexpected namespace"); + AddStatesSilently(NS_EVENT_STATE_LTR); } /** Typesafe, non-refcounting cast from nsIContent. Cheaper than QI. **/ diff --git a/dom/locales/en-US/chrome/layout/css.properties b/dom/locales/en-US/chrome/layout/css.properties index c3aed0a20980..bec986fd1110 100644 --- a/dom/locales/en-US/chrome/layout/css.properties +++ b/dom/locales/en-US/chrome/layout/css.properties @@ -114,6 +114,7 @@ PEMQExpectedFeatureValue=Found invalid value for media feature. PEBadFontBlockStart=Expected '{' to begin @font-face rule but found '%1$S'. PEBadFontBlockEnd=Expected '}' to end @font-face rule but found '%1$S'. PEAnonBoxNotAlone=Did not expect anonymous box. +PEBadDirValue=Expected 'ltr' or 'rtl' in direction selector but found '%1$S'. PESupportsConditionStartEOF='not' or '(' PESupportsConditionInParensStartEOF='not', '(' or identifier PESupportsConditionNotEOF='not' diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index 7d3f5a28a8e4..e1a747c18182 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -3595,10 +3595,12 @@ CSSParserImpl::ParsePseudoClassWithIdentArg(nsCSSSelector& aSelector, return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')') } - // -moz-locale-dir can only have values of 'ltr' or 'rtl'. - if (aType == nsCSSPseudoClasses::ePseudoClass_mozLocaleDir) { + // -moz-locale-dir and :dir can only have values of 'ltr' or 'rtl'. + if (aType == nsCSSPseudoClasses::ePseudoClass_mozLocaleDir || + aType == nsCSSPseudoClasses::ePseudoClass_dir) { if (!mToken.mIdent.EqualsLiteral("ltr") && !mToken.mIdent.EqualsLiteral("rtl")) { + REPORT_UNEXPECTED_TOKEN(PEBadDirValue); return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')') } } diff --git a/layout/style/nsCSSPseudoClassList.h b/layout/style/nsCSSPseudoClassList.h index b87ed3ad5185..23312179cc19 100644 --- a/layout/style/nsCSSPseudoClassList.h +++ b/layout/style/nsCSSPseudoClassList.h @@ -9,27 +9,45 @@ * This file contains the list of nsIAtoms and their values for CSS * pseudo-classes. It is designed to be used as inline input to * nsCSSPseudoClasses.cpp *only* through the magic of C preprocessing. - * All entries must be enclosed in the macros CSS_PSEUDO_CLASS or - * CSS_STATE_PSEUDO_CLASS which will have cruel and unusual things - * done to it. The entries should be kept in some sort of logical - * order. The first argument to CSS_PSEUDO_CLASS is the C++ - * identifier of the atom. The second argument is the string value of - * the atom. CSS_STATE_PSEUDO_CLASS also takes the name of the state - * bits that the class corresponds to. Only one of the bits needs to - * match for the pseudo-class to match. If CSS_STATE_PSEUDO_CLASS is - * not defined, it'll be automatically defined to CSS_PSEUDO_CLASS. + * All entries must be enclosed in the macros CSS_PSEUDO_CLASS, + * CSS_STATE_DEPENDENT_PSEUDO_CLASS, or CSS_STATE_PSEUDO_CLASS which + * will have cruel and unusual things done to them. The entries should + * be kept in some sort of logical order. The first argument to + * CSS_PSEUDO_CLASS is the C++ identifier of the atom. The second + * argument is the string value of the atom. + * CSS_STATE_DEPENDENT_PSEUDO_CLASS and CSS_STATE_PSEUDO_CLASS also take + * the name of the state bits that the class corresponds to. Only one + * of the bits needs to match for a CSS_STATE_PSEUDO_CLASS to match; + * CSS_STATE_DEPENDENT_PSEUDO_CLASS matching depends on a customized per-class + * algorithm which should be defined in SelectorMatches() in + * nsCSSRuleProcessor.cpp. + * + * If CSS_STATE_PSEUDO_CLASS is not defined, it'll be automatically + * defined to CSS_STATE_DEPENDENT_PSEUDO_CLASS; + * if CSS_STATE_DEPENDENT_PSEUDO_CLASS is not defined, it'll be + * automatically defined to CSS_PSEUDO_CLASS. */ // OUTPUT_CLASS=nsCSSPseudoClasses // MACRO_NAME=CSS_PSEUDO_CLASS +#ifdef DEFINED_CSS_STATE_DEPENDENT_PSEUDO_CLASS +#error "CSS_STATE_DEPENDENT_PSEUDO_CLASS shouldn't be defined" +#endif + +#ifndef CSS_STATE_DEPENDENT_PSEUDO_CLASS +#define CSS_STATE_DEPENDENT_PSEUDO_CLASS(_name, _value, _bit) \ + CSS_PSEUDO_CLASS(_name, _value) +#define DEFINED_CSS_STATE_DEPENDENT_PSEUDO_CLASS +#endif + #ifdef DEFINED_CSS_STATE_PSEUDO_CLASS -#error "This shouldn't be defined" +#error "CSS_STATE_PSEUDO_CLASS shouldn't be defined" #endif #ifndef CSS_STATE_PSEUDO_CLASS #define CSS_STATE_PSEUDO_CLASS(_name, _value, _bit) \ - CSS_PSEUDO_CLASS(_name, _value) + CSS_STATE_DEPENDENT_PSEUDO_CLASS(_name, _value, _bit) #define DEFINED_CSS_STATE_PSEUDO_CLASS #endif @@ -90,6 +108,11 @@ CSS_PSEUDO_CLASS(mozTableBorderNonzero, ":-moz-table-border-nonzero") // it doesn't actually get directly matched on in SelectorMatches. CSS_PSEUDO_CLASS(notPseudo, ":not") +// :dir(ltr) and :dir(rtl) match elements whose resolved directionality +// in the markup language is ltr or rtl respectively +CSS_STATE_DEPENDENT_PSEUDO_CLASS(dir, ":dir", + NS_EVENT_STATE_LTR | NS_EVENT_STATE_RTL) + CSS_STATE_PSEUDO_CLASS(link, ":link", NS_EVENT_STATE_UNVISITED) // what matches :link or :visited CSS_STATE_PSEUDO_CLASS(mozAnyLink, ":-moz-any-link", @@ -178,3 +201,8 @@ CSS_STATE_PSEUDO_CLASS(mozMeterSubSubOptimum, ":-moz-meter-sub-sub-optimum", #undef DEFINED_CSS_STATE_PSEUDO_CLASS #undef CSS_STATE_PSEUDO_CLASS #endif + +#ifdef DEFINED_CSS_STATE_DEPENDENT_PSEUDO_CLASS +#undef DEFINED_CSS_STATE_DEPENDENT_PSEUDO_CLASS +#undef CSS_STATE_DEPENDENT_PSEUDO_CLASS +#endif diff --git a/layout/style/nsCSSPseudoClasses.cpp b/layout/style/nsCSSPseudoClasses.cpp index e2046357a049..b2c19e355612 100644 --- a/layout/style/nsCSSPseudoClasses.cpp +++ b/layout/style/nsCSSPseudoClasses.cpp @@ -42,7 +42,8 @@ nsCSSPseudoClasses::HasStringArg(Type aType) return aType == ePseudoClass_lang || aType == ePseudoClass_mozEmptyExceptChildrenWithLocalname || aType == ePseudoClass_mozSystemMetric || - aType == ePseudoClass_mozLocaleDir; + aType == ePseudoClass_mozLocaleDir || + aType == ePseudoClass_dir; } bool diff --git a/layout/style/nsCSSRuleProcessor.cpp b/layout/style/nsCSSRuleProcessor.cpp index f6b57039445d..13f732dc55c3 100644 --- a/layout/style/nsCSSRuleProcessor.cpp +++ b/layout/style/nsCSSRuleProcessor.cpp @@ -1308,7 +1308,7 @@ struct NodeMatchContext { // event-state-dependent selector for any value of that event state. // So mStateMask contains the states that should NOT be tested. // - // NOTE: For |aStateMask| to work correctly, it's important that any + // NOTE: For |mStateMask| to work correctly, it's important that any // change that changes multiple state bits include all those state // bits in the notification. Otherwise, if multiple states change but // we do separate notifications then we might determine the style is @@ -1533,7 +1533,21 @@ checkGenericEmptyMatches(Element* aElement, return (child == nullptr); } -// An array of the states that are relevant for various pseudoclasses. +// Arrays of the states that are relevant for various pseudoclasses. +static const nsEventStates sPseudoClassStateDependences[] = { +#define CSS_PSEUDO_CLASS(_name, _value) \ + nsEventStates(), +#define CSS_STATE_DEPENDENT_PSEUDO_CLASS(_name, _value, _states) \ + _states, +#include "nsCSSPseudoClassList.h" +#undef CSS_STATE_DEPENDENT_PSEUDO_CLASS +#undef CSS_PSEUDO_CLASS + // Add more entries for our fake values to make sure we can't + // index out of bounds into this array no matter what. + nsEventStates(), + nsEventStates() +}; + static const nsEventStates sPseudoClassStates[] = { #define CSS_PSEUDO_CLASS(_name, _value) \ nsEventStates(), @@ -1556,7 +1570,7 @@ MOZ_STATIC_ASSERT(NS_ARRAY_LENGTH(sPseudoClassStates) == // * when non-null, it indicates that we're processing a negation, // which is done only when SelectorMatches calls itself recursively // * what it points to should be set to true whenever a test is skipped -// because of aStateMask +// because of aNodeMatchContent.mStateMask static bool SelectorMatches(Element* aElement, nsCSSSelector* aSelector, NodeMatchContext& aNodeMatchContext, @@ -1997,6 +2011,38 @@ static bool SelectorMatches(Element* aElement, } break; + case nsCSSPseudoClasses::ePseudoClass_dir: + { + if (aDependence) { + nsEventStates states + = sPseudoClassStateDependences[pseudoClass->mType]; + if (aNodeMatchContext.mStateMask.HasAtLeastOneOfStates(states)) { + *aDependence = true; + return false; + } + } + + // if we only had to consider HTML, directionality would be exclusively + // LTR or RTL, and this could be just + // + // if (dirString.EqualsLiteral("rtl") != + // aElement->StyleState().HasState(NS_EVENT_STATE_RTL) + // + // However, in markup languages where there is no direction attribute + // we have to consider the possibility that neither dir(rtl) nor + // dir(ltr) matches. + nsEventStates state = aElement->StyleState(); + bool elementIsRTL = state.HasState(NS_EVENT_STATE_RTL); + bool elementIsLTR = state.HasState(NS_EVENT_STATE_LTR); + nsDependentString dirString(pseudoClass->u.mString); + + if ((dirString.EqualsLiteral("rtl") && !elementIsRTL) || + (dirString.EqualsLiteral("ltr") && !elementIsLTR)) { + return false; + } + } + break; + default: NS_ABORT_IF_FALSE(false, "How did that happen?"); } @@ -2128,10 +2174,10 @@ static bool SelectorMatches(Element* aElement, bool dependence = false; result = !SelectorMatches(aElement, negation, aNodeMatchContext, aTreeMatchContext, &dependence); - // If the selector does match due to the dependence on aStateMask, - // then we want to keep result true so that the final result of - // SelectorMatches is true. Doing so tells StateEnumFunc that - // there is a dependence on the state. + // If the selector does match due to the dependence on + // aNodeMatchContext.mStateMask, then we want to keep result true + // so that the final result of SelectorMatches is true. Doing so + // tells StateEnumFunc that there is a dependence on the state. result = result || dependence; } } @@ -2665,7 +2711,7 @@ nsEventStates ComputeSelectorStateDependence(nsCSSSelector& aSelector) if (pseudoClass->mType >= nsCSSPseudoClasses::ePseudoClass_Count) { continue; } - states |= sPseudoClassStates[pseudoClass->mType]; + states |= sPseudoClassStateDependences[pseudoClass->mType]; } return states; } From e4b34697750b53be57a04416f2b7c9fabef7b96c Mon Sep 17 00:00:00 2001 From: Simon Montagu Date: Tue, 17 Apr 2012 07:03:10 +0300 Subject: [PATCH 126/169] Add support for :dir(ltr/rtl) CSS selector, content part, Bug 562169, r=bz --- content/base/public/DirectionalityUtils.h | 58 +++++++++++ content/base/public/Element.h | 13 +++ content/base/public/Makefile.in | 1 + content/base/public/nsIDocument.h | 8 ++ content/base/public/nsINode.h | 15 ++- content/base/src/DirectionalityUtils.cpp | 96 +++++++++++++++++++ content/base/src/Makefile.in | 1 + content/base/src/nsDocument.cpp | 14 ++- content/base/src/nsDocument.h | 6 ++ content/base/src/nsGenericElement.cpp | 16 ++++ content/base/src/nsGkAtomList.h | 1 + .../html/content/src/nsGenericHTMLElement.cpp | 34 +++++++ .../html/content/src/nsGenericHTMLElement.h | 3 + 13 files changed, 264 insertions(+), 2 deletions(-) create mode 100644 content/base/public/DirectionalityUtils.h create mode 100644 content/base/src/DirectionalityUtils.cpp diff --git a/content/base/public/DirectionalityUtils.h b/content/base/public/DirectionalityUtils.h new file mode 100644 index 000000000000..0973e7588ded --- /dev/null +++ b/content/base/public/DirectionalityUtils.h @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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/. */ + +#ifndef DirectionalityUtils_h___ +#define DirectionalityUtils_h___ + +class nsIContent; +class nsIDocument; +class nsINode; + +namespace mozilla { +namespace dom { +class Element; +} // namespace dom +} // namespace mozilla + +namespace mozilla { + +namespace directionality { + +enum Directionality { + eDir_NotSet = 0, + eDir_RTL = 1, + eDir_LTR = 2 +}; + +void SetDirectionality(mozilla::dom::Element* aElement, Directionality aDir, + bool aNotify = true); + +/** + * Set the directionality of an element according to the algorithm defined at + * http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-directionality, + * not including elements with auto direction. + * + * @return the directionality that the element was set to + */ +Directionality RecomputeDirectionality(mozilla::dom::Element* aElement, + bool aNotify = true); + +/** + * Set the directionality of any descendants of a node that do not themselves + * have a dir attribute. + * For performance reasons we walk down the descendant tree in the rare case + * of setting the dir attribute, rather than walking up the ancestor tree in + * the much more common case of getting the element's directionality. + */ +void SetDirectionalityOnDescendants(mozilla::dom::Element* aElement, + Directionality aDir, + bool aNotify = true); + +} // end namespace directionality + +} // end namespace mozilla + +#endif /* DirectionalityUtils_h___ */ diff --git a/content/base/public/Element.h b/content/base/public/Element.h index 4d1b51b1acbd..141d5c5932a7 100644 --- a/content/base/public/Element.h +++ b/content/base/public/Element.h @@ -10,6 +10,7 @@ #include "mozilla/dom/FragmentOrElement.h" // for base class #include "nsChangeHint.h" // for enum #include "nsEventStates.h" // for member +#include "mozilla/dom/DirectionalityUtils.h" class nsEventStateManager; class nsFocusManager; @@ -216,6 +217,18 @@ public: */ virtual nsIAtom *GetClassAttributeName() const = 0; + inline mozilla::directionality::Directionality GetDirectionality() const { + if (HasFlag(NODE_HAS_DIRECTION_RTL)) { + return mozilla::directionality::eDir_RTL; + } + + if (HasFlag(NODE_HAS_DIRECTION_LTR)) { + return mozilla::directionality::eDir_LTR; + } + + return mozilla::directionality::eDir_NotSet; + } + protected: /** * Method to get the _intrinsic_ content state of this element. This is the diff --git a/content/base/public/Makefile.in b/content/base/public/Makefile.in index 49c521897795..5d92d5876f2b 100644 --- a/content/base/public/Makefile.in +++ b/content/base/public/Makefile.in @@ -48,6 +48,7 @@ $(NULL) EXPORTS_NAMESPACES = mozilla/dom mozilla EXPORTS_mozilla/dom = \ + DirectionalityUtils.h \ Element.h \ FragmentOrElement.h \ FromParser.h \ diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index 16307c8d5cf1..0845a2954312 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -23,6 +23,7 @@ #include "nsPIDOMWindow.h" // for use in inline functions #include "nsPropertyTable.h" // for member #include "nsTHashtable.h" // for member +#include "mozilla/dom/DirectionalityUtils.h" class imgIRequest; class nsAString; @@ -397,6 +398,10 @@ public: { mBidiOptions = aBidiOptions; } + + inline mozilla::directionality::Directionality GetDocumentDirectionality() { + return mDirectionality; + } /** * Access HTTP header data (this may also get set from other @@ -1853,6 +1858,9 @@ protected: // defined in nsBidiUtils.h PRUint32 mBidiOptions; + // The root directionality of this document. + mozilla::directionality::Directionality mDirectionality; + nsCString mContentLanguage; private: nsCString mContentType; diff --git a/content/base/public/nsINode.h b/content/base/public/nsINode.h index 0d79acf33736..189d64265507 100644 --- a/content/base/public/nsINode.h +++ b/content/base/public/nsINode.h @@ -145,8 +145,16 @@ enum { // Set if the node has had :hover selectors matched against it NODE_HAS_RELEVANT_HOVER_RULES = 0x00080000U, + // Set if the node has right-to-left directionality + NODE_HAS_DIRECTION_RTL = 0x00100000U, + + // Set if the node has left-to-right directionality + NODE_HAS_DIRECTION_LTR = 0x00200000U, + + NODE_ALL_DIRECTION_FLAGS = NODE_HAS_DIRECTION_LTR | NODE_HAS_DIRECTION_RTL, + // Remaining bits are node type specific. - NODE_TYPE_SPECIFIC_BITS_OFFSET = 20 + NODE_TYPE_SPECIFIC_BITS_OFFSET = 22 }; /** @@ -1279,6 +1287,8 @@ private: NodeIsContent, // Set if the node has animations or transitions ElementHasAnimations, + // Set if node has a dir attribute with a valid value (ltr or rtl) + NodeHasValidDirAttribute, // Guard value BooleanFlagCount }; @@ -1346,6 +1356,9 @@ public: void ClearPointerLock() { ClearBoolFlag(ElementHasPointerLock); } bool MayHaveAnimations() { return GetBoolFlag(ElementHasAnimations); } void SetMayHaveAnimations() { SetBoolFlag(ElementHasAnimations); } + void SetHasValidDir() { SetBoolFlag(NodeHasValidDirAttribute); } + void ClearHasValidDir() { ClearBoolFlag(NodeHasValidDirAttribute); } + bool HasValidDir() const { return GetBoolFlag(NodeHasValidDirAttribute); } protected: void SetParentIsContent(bool aValue) { SetBoolFlag(ParentIsContent, aValue); } void SetInDocument() { SetBoolFlag(IsInDocument); } diff --git a/content/base/src/DirectionalityUtils.cpp b/content/base/src/DirectionalityUtils.cpp new file mode 100644 index 000000000000..29dfb30fd732 --- /dev/null +++ b/content/base/src/DirectionalityUtils.cpp @@ -0,0 +1,96 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 sw=2 et tw=78: */ +/* 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/. */ + +#include "mozilla/dom/DirectionalityUtils.h" +#include "nsINode.h" +#include "nsIContent.h" +#include "nsIDocument.h" +#include "mozilla/dom/Element.h" +#include "nsIDOMNodeFilter.h" +#include "nsTreeWalker.h" +#include "nsIDOMHTMLDocument.h" + + +namespace mozilla { + +namespace directionality { + +typedef mozilla::dom::Element Element; + +void +SetDirectionality(Element* aElement, Directionality aDir, bool aNotify) +{ + aElement->UnsetFlags(NODE_ALL_DIRECTION_FLAGS); + switch (aDir) { + case eDir_RTL: + aElement->SetFlags(NODE_HAS_DIRECTION_RTL); + break; + case eDir_LTR: + aElement->SetFlags(NODE_HAS_DIRECTION_LTR); + break; + default: + break; + } + + aElement->UpdateState(aNotify); +} + +Directionality +RecomputeDirectionality(Element* aElement, bool aNotify) +{ + Directionality dir = eDir_LTR; + + if (aElement->HasValidDir()) { + dir = aElement->GetDirectionality(); + } else { + Element* parent = aElement->GetElementParent(); + if (parent) { + // If the element doesn't have an explicit dir attribute with a valid + // value, the directionality is the same as the parent element (but + // don't propagate the parent directionality if it isn't set yet). + Directionality parentDir = parent->GetDirectionality(); + if (parentDir != eDir_NotSet) { + dir = parentDir; + } + } else { + // If there is no parent element, the directionality is the same as the + // document direction. + Directionality documentDir = + aElement->OwnerDoc()->GetDocumentDirectionality(); + if (documentDir != eDir_NotSet) { + dir = documentDir; + } + } + + SetDirectionality(aElement, dir, aNotify); + } + return dir; +} + +void +SetDirectionalityOnDescendants(Element* aElement, Directionality aDir, + bool aNotify) +{ + for (nsIContent* child = aElement->GetFirstChild(); child; ) { + if (!child->IsElement()) { + child = child->GetNextNode(aElement); + continue; + } + + Element* element = child->AsElement(); + if (element->HasValidDir()) { + child = child->GetNextNonChildNode(aElement); + continue; + } + SetDirectionality(element, aDir, aNotify); + child = child->GetNextNode(aElement); + } +} + +} // end namespace directionality + +} // end namespace mozilla + diff --git a/content/base/src/Makefile.in b/content/base/src/Makefile.in index fdec933a82b7..c7c1d95097a6 100644 --- a/content/base/src/Makefile.in +++ b/content/base/src/Makefile.in @@ -53,6 +53,7 @@ LOCAL_INCLUDES = \ $(NULL) CPPSRCS = \ + DirectionalityUtils.cpp \ nsAtomListUtils.cpp \ nsAttrAndChildArray.cpp \ nsAttrValue.cpp \ diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 643fb2e05b44..aa46e89ffc0f 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -91,6 +91,7 @@ #include "nsXMLEventsManager.h" #include "nsBidiUtils.h" +#include "mozilla/dom/DirectionalityUtils.h" #include "nsIDOMUserDataHandler.h" #include "nsIDOMXPathEvaluator.h" @@ -170,6 +171,7 @@ using namespace mozilla; using namespace mozilla::dom; +using namespace mozilla::directionality; typedef nsTArray LinkArray; @@ -1510,7 +1512,8 @@ nsIDocument::nsIDocument() mAllowDNSPrefetch(true), mIsBeingUsedAsImage(false), mHasLinksToUpdate(false), - mPartID(0) + mPartID(0), + mDirectionality(eDir_LTR) { SetInDocument(); } @@ -5583,6 +5586,15 @@ nsDocument::SetDir(const nsAString& aDirection) // No presentation; just set it on ourselves SetBidiOptions(options); } + Directionality dir = elt->mValue == IBMBIDI_TEXTDIRECTION_RTL ? + eDir_RTL : eDir_LTR; + SetDocumentDirectionality(dir); + // Set the directionality of the root element and its descendants, if any + Element* rootElement = GetRootElement(); + if (rootElement) { + SetDirectionality(rootElement, dir, true); + SetDirectionalityOnDescendants(rootElement, dir); + } } break; diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h index bbe012601d80..3ef75fda92b2 100644 --- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -1048,6 +1048,12 @@ protected: nsIContent* GetFirstBaseNodeWithHref(); nsresult SetFirstBaseNodeWithHref(nsIContent *node); + inline void + SetDocumentDirectionality(mozilla::directionality::Directionality aDir) + { + mDirectionality = aDir; + } + // Get the first element with the given IsNodeOfType type, or // return null if there isn't one nsIContent* GetTitleContent(PRUint32 aNodeType); diff --git a/content/base/src/nsGenericElement.cpp b/content/base/src/nsGenericElement.cpp index e591e7ed11af..a421bd5299f0 100644 --- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -51,6 +51,7 @@ #include "nsIDOMMutationEvent.h" #include "nsMutationEvent.h" #include "nsNodeUtils.h" +#include "mozilla/dom/DirectionalityUtils.h" #include "nsDocument.h" #include "nsAttrValueOrString.h" #ifdef MOZ_XUL @@ -128,6 +129,7 @@ using namespace mozilla; using namespace mozilla::dom; +using namespace mozilla::directionality; nsEventStates Element::IntrinsicState() const @@ -1358,6 +1360,13 @@ nsGenericElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, SetSubtreeRootPointer(aParent->SubtreeRoot()); } + // This has to be here, rather than in nsGenericHTMLElement::BindToTree, + // because it has to happen after updating the parent pointer, but before + // recursively binding the kids. + if (IsHTML()) { + RecomputeDirectionality(this, false); + } + // If NODE_FORCE_XBL_BINDINGS was set we might have anonymous children // that also need to be told that they are moving. nsresult rv; @@ -1543,6 +1552,13 @@ nsGenericElement::UnbindFromTree(bool aDeep, bool aNullParent) } } + // This has to be here, rather than in nsGenericHTMLElement::UnbindFromTree, + // because it has to happen after unsetting the parent pointer, but before + // recursively unbinding the kids. + if (IsHTML()) { + RecomputeDirectionality(this, false); + } + if (aDeep) { // Do the kids. Don't call GetChildCount() here since that'll force // XUL to generate template children, which there is no need for since diff --git a/content/base/src/nsGkAtomList.h b/content/base/src/nsGkAtomList.h index ded8059f8ba9..82f010b68a80 100644 --- a/content/base/src/nsGkAtomList.h +++ b/content/base/src/nsGkAtomList.h @@ -270,6 +270,7 @@ GK_ATOM(dialog, "dialog") GK_ATOM(difference, "difference") GK_ATOM(digit, "digit") GK_ATOM(dir, "dir") +GK_ATOM(directionality, "directionality") GK_ATOM(disableOutputEscaping, "disable-output-escaping") GK_ATOM(disabled, "disabled") GK_ATOM(display, "display") diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp index 2f502f79a2cd..da3e83ecd178 100644 --- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -53,6 +53,7 @@ #include "nsHTMLParts.h" #include "nsContentUtils.h" +#include "mozilla/dom/DirectionalityUtils.h" #include "nsString.h" #include "nsUnicharUtils.h" #include "nsGkAtoms.h" @@ -96,6 +97,7 @@ using namespace mozilla; using namespace mozilla::dom; +using namespace mozilla::directionality; class nsINodeInfo; class nsIDOMNodeList; @@ -1687,6 +1689,24 @@ nsGenericHTMLElement::UpdateEditableState(bool aNotify) nsStyledElement::UpdateEditableState(aNotify); } +nsEventStates +nsGenericHTMLElement::IntrinsicState() const +{ + nsEventStates state = nsGenericHTMLElementBase::IntrinsicState(); + + if (GetDirectionality() == eDir_RTL) { + state |= NS_EVENT_STATE_RTL; + state &= ~NS_EVENT_STATE_LTR; + } else { // at least for HTML, directionality is exclusively LTR or RTL + NS_ASSERTION(GetDirectionality() == eDir_LTR, + "HTML element's directionality must be either RTL or LTR"); + state |= NS_EVENT_STATE_LTR; + state &= ~NS_EVENT_STATE_RTL; + } + + return state; +} + nsresult nsGenericHTMLElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, nsIContent* aBindingParent, @@ -1889,6 +1909,20 @@ nsGenericHTMLElement::AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName, else if (aNotify && aName == nsGkAtoms::spellcheck) { SyncEditorsOnSubtree(this); } + else if (aName == nsGkAtoms::dir) { + Directionality dir; + if (aValue && + (aValue->Equals(nsGkAtoms::ltr, eIgnoreCase) || + aValue->Equals(nsGkAtoms::rtl, eIgnoreCase))) { + SetHasValidDir(); + dir = aValue->Equals(nsGkAtoms::rtl, eIgnoreCase) ? eDir_RTL : eDir_LTR; + SetDirectionality(this, dir, aNotify); + } else { + ClearHasValidDir(); + dir = RecomputeDirectionality(this, aNotify); + } + SetDirectionalityOnDescendants(this, dir, aNotify); + } } return nsGenericHTMLElementBase::AfterSetAttr(aNamespaceID, aName, diff --git a/content/html/content/src/nsGenericHTMLElement.h b/content/html/content/src/nsGenericHTMLElement.h index b1e04ea37824..a4bbd99db54b 100644 --- a/content/html/content/src/nsGenericHTMLElement.h +++ b/content/html/content/src/nsGenericHTMLElement.h @@ -50,6 +50,7 @@ public: NS_ASSERTION(mNodeInfo->NamespaceID() == kNameSpaceID_XHTML, "Unexpected namespace"); AddStatesSilently(NS_EVENT_STATE_LTR); + SetFlags(NODE_HAS_DIRECTION_LTR); } /** Typesafe, non-refcounting cast from nsIContent. Cheaper than QI. **/ @@ -203,6 +204,8 @@ public: virtual void UpdateEditableState(bool aNotify); + virtual nsEventStates IntrinsicState() const; + // Helper for setting our editable flag and notifying void DoSetEditableFlag(bool aEditable, bool aNotify) { SetEditableFlag(aEditable); From 6b41ad69721263c4357e253a0c7889ce76da2e08 Mon Sep 17 00:00:00 2001 From: Mark Capella <markcapella@twcny.rr.com> Date: Wed, 8 Aug 2012 00:51:28 -0400 Subject: [PATCH 127/169] Bug 772272 - Remove do_load_httpd_js from xpcshell tests, r=ted, f=gps --- .../extensions/test/unit/test_bug463819.js | 20 ++++++++-------- .../test/xpcshell/test_AddonRepository.js | 4 ++-- .../xpcshell/test_AddonRepository_cache.js | 4 ++-- .../test_AddonRepository_compatmode.js | 4 ++-- .../test/xpcshell/test_backgroundupdate.js | 4 ++-- .../test/xpcshell/test_badschema.js | 4 ++-- .../test/xpcshell/test_blocklistchange.js | 10 +++++--- .../test/xpcshell/test_bootstrap.js | 4 ++-- .../test/xpcshell/test_bug299716.js | 4 ++-- .../test/xpcshell/test_bug299716_2.js | 4 ++-- .../test/xpcshell/test_bug324121.js | 4 ++-- .../test/xpcshell/test_bug335238.js | 11 +++++---- .../test/xpcshell/test_bug384052.js | 4 ++-- .../test/xpcshell/test_bug394300.js | 4 ++-- .../test/xpcshell/test_bug424262.js | 6 ++--- .../test/xpcshell/test_bug430120.js | 4 ++-- .../test/xpcshell/test_bug449027.js | 23 +++++++++++-------- .../test/xpcshell/test_bug455906.js | 8 +++++-- .../test/xpcshell/test_bug470377_1.js | 4 ++-- .../xpcshell/test_bug470377_1_strictcompat.js | 4 ++-- .../test/xpcshell/test_bug470377_2.js | 4 ++-- .../test/xpcshell/test_bug514327_3.js | 11 +++++---- .../test/xpcshell/test_bug542391.js | 8 +++++-- .../test/xpcshell/test_bug554133.js | 4 ++-- .../test/xpcshell/test_bug570173.js | 4 ++-- .../test/xpcshell/test_bug619730.js | 8 +++++-- .../test/xpcshell/test_bug620837.js | 4 ++-- .../test/xpcshell/test_bug655254.js | 4 ++-- .../test/xpcshell/test_compatoverrides.js | 4 ++-- .../extensions/test/xpcshell/test_corrupt.js | 4 ++-- .../xpcshell/test_corrupt_strictcompat.js | 4 ++-- .../test/xpcshell/test_dictionary.js | 4 ++-- .../test/xpcshell/test_filepointer.js | 10 ++++---- .../test/xpcshell/test_gfxBlacklist_Device.js | 4 ++-- .../xpcshell/test_gfxBlacklist_DriverNew.js | 4 ++-- .../test_gfxBlacklist_Equal_DriverNew.js | 4 ++-- .../test_gfxBlacklist_Equal_DriverOld.js | 4 ++-- .../xpcshell/test_gfxBlacklist_Equal_OK.js | 4 ++-- .../test_gfxBlacklist_GTE_DriverOld.js | 4 ++-- .../test/xpcshell/test_gfxBlacklist_GTE_OK.js | 4 ++-- .../test_gfxBlacklist_No_Comparison.js | 4 ++-- .../test/xpcshell/test_gfxBlacklist_OK.js | 4 ++-- .../test/xpcshell/test_gfxBlacklist_OS.js | 4 ++-- .../test/xpcshell/test_gfxBlacklist_Vendor.js | 4 ++-- .../test/xpcshell/test_gfxBlacklist_prefs.js | 4 ++-- .../extensions/test/xpcshell/test_hotfix.js | 4 ++-- .../extensions/test/xpcshell/test_install.js | 13 +++++++---- .../xpcshell/test_install_strictcompat.js | 13 +++++++---- .../extensions/test/xpcshell/test_locked.js | 4 ++-- .../test/xpcshell/test_locked_strictcompat.js | 4 ++-- .../extensions/test/xpcshell/test_migrate4.js | 4 ++-- .../extensions/test/xpcshell/test_update.js | 4 ++-- .../test/xpcshell/test_update_compatmode.js | 6 ++--- .../test/xpcshell/test_update_ignorecompat.js | 4 ++-- .../test/xpcshell/test_update_strictcompat.js | 4 ++-- .../test/xpcshell/test_updatecheck.js | 4 ++-- .../extensions/test/xpcshell/test_updateid.js | 4 ++-- 57 files changed, 177 insertions(+), 146 deletions(-) diff --git a/toolkit/mozapps/extensions/test/unit/test_bug463819.js b/toolkit/mozapps/extensions/test/unit/test_bug463819.js index 9bcefbaa086c..d4467c8b6117 100644 --- a/toolkit/mozapps/extensions/test/unit/test_bug463819.js +++ b/toolkit/mozapps/extensions/test/unit/test_bug463819.js @@ -12,38 +12,38 @@ const INSTALLERROR_SOFTBLOCKED = -10; gPrefs.setBoolPref("extensions.checkUpdateSecurity", false); // Get the HTTP server. -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var testserver; // This allows the EM to attempt to display errors to the user without failing var promptService = { alert: function(aParent, aDialogTitle, aText) { }, - + alertCheck: function(aParent, aDialogTitle, aText, aCheckMsg, aCheckState) { }, - + confirm: function(aParent, aDialogTitle, aText) { }, - + confirmCheck: function(aParent, aDialogTitle, aText, aCheckMsg, aCheckState) { }, - + confirmEx: function(aParent, aDialogTitle, aText, aButtonFlags, aButton0Title, aButton1Title, aButton2Title, aCheckMsg, aCheckState) { }, - + prompt: function(aParent, aDialogTitle, aText, aValue, aCheckMsg, aCheckState) { }, - + promptUsernameAndPassword: function(aParent, aDialogTitle, aText, aUsername, aPassword, aCheckMsg, aCheckState) { }, promptPassword: function(aParent, aDialogTitle, aText, aPassword, aCheckMsg, aCheckState) { }, - + select: function(aParent, aDialogTitle, aText, aCount, aSelectList, aOutSelection) { }, - + QueryInterface: function(iid) { if (iid.equals(Components.interfaces.nsIPromptService) || iid.equals(Components.interfaces.nsISupports)) @@ -130,7 +130,7 @@ function run_test() { blocklist.copyTo(gProfD, "blocklist.xml"); // Create and configure the HTTP server. - testserver = new nsHttpServer(); + testserver = new HttpServer(); testserver.registerDirectory("/", do_get_file("data")); testserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository.js b/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository.js index 49a9f90137a5..3417353a2e4c 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository.js @@ -6,7 +6,7 @@ Components.utils.import("resource://gre/modules/AddonRepository.jsm"); -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var gServer; const PREF_GETADDONS_BROWSEADDONS = "extensions.getAddons.browseAddons"; @@ -364,7 +364,7 @@ function run_test() { installAllFiles([do_get_addon("test_AddonRepository_1")], function() { restartManager(); - gServer = new nsHttpServer(); + gServer = new HttpServer(); // Register other add-on XPI files gServer.registerFile(INSTALL_URL2, diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository_cache.js b/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository_cache.js index 00bd0ceb6536..2dc08489d8b1 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository_cache.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository_cache.js @@ -6,7 +6,7 @@ Components.utils.import("resource://gre/modules/AddonRepository.jsm"); -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); let gServer; const PORT = 4444; @@ -533,7 +533,7 @@ function run_test() { installAllFiles(ADDON_FILES, function() { restartManager(); - gServer = new nsHttpServer(); + gServer = new HttpServer(); gServer.registerDirectory("/data/", do_get_file("data")); gServer.start(PORT); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository_compatmode.js b/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository_compatmode.js index 83f896800bc9..78d7e4ac6bb2 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository_compatmode.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository_compatmode.js @@ -7,7 +7,7 @@ const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url"; -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var gServer; var COMPATIBILITY_PREF; @@ -29,7 +29,7 @@ function run_test() { COMPATIBILITY_PREF = "extensions.checkCompatibility." + version; // Create and configure the HTTP server. - gServer = new nsHttpServer(); + gServer = new HttpServer(); gServer.registerDirectory("/data/", do_get_file("data")); gServer.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_backgroundupdate.js b/toolkit/mozapps/extensions/test/xpcshell/test_backgroundupdate.js index 19d05ba337f7..4d56239f236f 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_backgroundupdate.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_backgroundupdate.js @@ -7,7 +7,7 @@ // The test extension uses an insecure update url. Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var testserver; const profileDir = gProfD.clone(); profileDir.append("extensions"); @@ -16,7 +16,7 @@ function run_test() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); // Create and configure the HTTP server. - testserver = new nsHttpServer(); + testserver = new HttpServer(); testserver.registerDirectory("/data/", do_get_file("data")); testserver.registerDirectory("/addons/", do_get_file("addons")); testserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_badschema.js b/toolkit/mozapps/extensions/test/xpcshell/test_badschema.js index a037b6a19022..416b3a6085dd 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_badschema.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_badschema.js @@ -5,7 +5,7 @@ // Checks that we rebuild something sensible from a database with a bad schema -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var testserver; // The test extension uses an insecure update url. @@ -143,7 +143,7 @@ function run_test() { writeInstallRDFForExtension(theme2, profileDir); // Create and configure the HTTP server. - testserver = new nsHttpServer(); + testserver = new HttpServer(); testserver.registerDirectory("/addons/", do_get_file("addons")); testserver.registerDirectory("/data/", do_get_file("data")); testserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_blocklistchange.js b/toolkit/mozapps/extensions/test/xpcshell/test_blocklistchange.js index 839a08c3ae26..5d016bd0d9e4 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_blocklistchange.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_blocklistchange.js @@ -27,14 +27,18 @@ // softblocked and have to be manually re-enabled if they become completely // unblocked (bug 657520) +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; + const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul"; -Components.utils.import("resource://gre/modules/NetUtil.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); // Allow insecure updates Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false) -do_load_httpd_js(); +Cu.import("resource://testing-common/httpd.js"); var testserver; var default_theme = { @@ -512,7 +516,7 @@ function check_addon(aAddon, aExpectedVersion, aExpectedUserDisabled, function run_test() { // Create and configure the HTTP server. - testserver = new nsHttpServer(); + testserver = new HttpServer(); testserver.registerDirectory("/data/", do_get_file("data/blocklistchange")); testserver.registerDirectory("/addons/", do_get_file("addons")); testserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap.js b/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap.js index 346c92e578d1..f1eafd16f5cd 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap.js @@ -27,7 +27,7 @@ userExtDir.append("extensions2"); userExtDir.append(gAppInfo.ID); registerDirectory("XREUSysExt", userExtDir.parent); -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var testserver; function resetPrefs() { @@ -87,7 +87,7 @@ function run_test() { resetPrefs(); // Create and configure the HTTP server. - testserver = new nsHttpServer(); + testserver = new HttpServer(); testserver.registerDirectory("/addons/", do_get_file("addons")); testserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug299716.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug299716.js index 9cb42d94090a..5de941f32d85 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug299716.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug299716.js @@ -26,7 +26,7 @@ const checkListener = { } // Get the HTTP server. -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var testserver; var ADDONS = [ @@ -128,7 +128,7 @@ function run_test() { do_check_true(xpiFile.exists()); // Create and configure the HTTP server. - testserver = new nsHttpServer(); + testserver = new HttpServer(); testserver.registerDirectory("/addons/", addonsDir); testserver.registerDirectory("/data/", dataDir); testserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug299716_2.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug299716_2.js index b587b5f58642..c183edad494e 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug299716_2.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug299716_2.js @@ -7,7 +7,7 @@ Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); // Get the HTTP server. -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var testserver; var ADDON = { @@ -24,7 +24,7 @@ function run_test() { const addonsDir = do_get_addon(ADDON.addon).parent; // Create and configure the HTTP server. - testserver = new nsHttpServer(); + testserver = new HttpServer(); testserver.registerDirectory("/addons/", addonsDir); testserver.registerDirectory("/data/", dataDir); testserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug324121.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug324121.js index f7dd7ddc77a8..6a4d01626f4a 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug324121.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug324121.js @@ -7,7 +7,7 @@ Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); // Get the HTTP server. -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var testserver; var next_test = null; @@ -130,7 +130,7 @@ function run_test() { const dataDir = do_get_file("data"); // Create and configure the HTTP server. - testserver = new nsHttpServer(); + testserver = new HttpServer(); testserver.registerDirectory("/data/", dataDir); testserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug335238.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug335238.js index f20004d181a3..7b62304dc5fd 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug335238.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug335238.js @@ -9,7 +9,10 @@ const PREF_SELECTED_LOCALE = "general.useragent.locale"; // Disables security checking our updates which haven't been signed Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); -do_load_httpd_js(); +const Ci = Components.interfaces; +const Cu = Components.utils; + +Cu.import("resource://testing-common/httpd.js"); // This is the data we expect to see sent as part of the update url. var EXPECTED = [ @@ -94,8 +97,8 @@ var BlocklistService = { }, QueryInterface: function(iid) { - if (iid.equals(Components.interfaces.nsIBlocklistService) - || iid.equals(Components.interfaces.nsISupports)) + if (iid.equals(Ci.nsIBlocklistService) + || iid.equals(Ci.nsISupports)) return this; throw Components.results.NS_ERROR_NO_INTERFACE; @@ -148,7 +151,7 @@ function run_test() { do_test_pending(); createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9"); - server = new nsHttpServer(); + server = new HttpServer(); server.registerPathHandler("/0", requestHandler); server.registerPathHandler("/1", requestHandler); server.registerPathHandler("/2", requestHandler); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug384052.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug384052.js index 6cbaabf7c8ff..623c7d22d82a 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug384052.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug384052.js @@ -9,7 +9,7 @@ var gComponentRegistrar = Components.manager.QueryInterface(AM_Ci.nsIComponentRe var gCategoryManager = AM_Cc["@mozilla.org/categorymanager;1"].getService(AM_Ci.nsICategoryManager); // Get the HTTP server. -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var testserver; // Factory for our parameter handler @@ -37,7 +37,7 @@ function initTest() createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9"); // Create and configure the HTTP server. - testserver = new nsHttpServer(); + testserver = new HttpServer(); testserver.registerPathHandler("/update.rdf", function(aRequest, aResponse) { gSeenExpectedURL = aRequest.queryString == gExpectedQuery; aResponse.setStatusLine(null, 404, "Not Found"); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug394300.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug394300.js index af84a622e128..bd393b91c48f 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug394300.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug394300.js @@ -6,7 +6,7 @@ // Disables security checking our updates which haven't been signed Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var server; // nsIAddonUpdateCheckListener implementation @@ -45,7 +45,7 @@ function run_test() do_check_neq(updates[0], null); do_check_neq(updates[1], null); - server = new nsHttpServer(); + server = new HttpServer(); server.registerDirectory("/", do_get_file("data")); server.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug424262.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug424262.js index 3c544a32b76d..a00914c6176b 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug424262.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug424262.js @@ -6,7 +6,7 @@ Components.utils.import("resource://gre/modules/AddonRepository.jsm"); const PREF_GETADDONS_GETRECOMMENDED = "extensions.getAddons.recommended.url"; -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var server; var RESULTS = [ null, @@ -44,13 +44,13 @@ function run_test() createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9"); startupManager(); - server = new nsHttpServer(); + server = new HttpServer(); server.registerDirectory("/", do_get_file("data")); server.start(4444); // Point the addons repository to the test server Services.prefs.setCharPref(PREF_GETADDONS_GETRECOMMENDED, "http://localhost:4444/test_bug424262.xml"); - + do_check_neq(AddonRepository, null); do_test_pending(); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug430120.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug430120.js index 235182bce544..86e2a57d0089 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug430120.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug430120.js @@ -13,7 +13,7 @@ const PREF_GENERAL_USERAGENT_LOCALE = "general.useragent.locale"; const CATEGORY_UPDATE_TIMER = "update-timer"; // Get the HTTP server. -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var testserver; var gOSVersion; var gBlocklist; @@ -103,7 +103,7 @@ function run_test() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9"); - testserver = new nsHttpServer(); + testserver = new HttpServer(); testserver.registerPathHandler("/1", failHandler); testserver.registerPathHandler("/2", pathHandler); testserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug449027.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug449027.js index 2b2fe8f22f4e..607539830cb4 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug449027.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug449027.js @@ -4,7 +4,10 @@ */ const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul"; -do_load_httpd_js(); +const Ci = Components.interfaces; +const Cu = Components.utils; + +Cu.import("resource://testing-common/httpd.js"); var ADDONS = [{ id: "test_bug449027_1@tests.mozilla.org", @@ -372,10 +375,10 @@ var PluginHost = { }, QueryInterface: function(iid) { - if (iid.equals(Components.interfaces.nsIPluginHost) - || iid.equals(Components.interfaces.nsISupports)) + if (iid.equals(Ci.nsIPluginHost) + || iid.equals(Ci.nsISupports)) return this; - + throw Components.results.NS_ERROR_NO_INTERFACE; } } @@ -408,8 +411,8 @@ var WindowWatcher = { }, QueryInterface: function(iid) { - if (iid.equals(Components.interfaces.nsIWindowWatcher) - || iid.equals(Components.interfaces.nsISupports)) + if (iid.equals(Ci.nsIWindowWatcher) + || iid.equals(Ci.nsISupports)) return this; throw Components.results.NS_ERROR_NO_INTERFACE; @@ -423,7 +426,7 @@ var WindowWatcherFactory = { return WindowWatcher.QueryInterface(iid); } }; -var registrar = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar); +var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); registrar.registerFactory(Components.ID("{721c3e73-969e-474b-a6dc-059fd288c428}"), "Fake Plugin Host", "@mozilla.org/plugin/host;1", PluginHostFactory); @@ -455,7 +458,7 @@ function create_addon(addon) { target.append("install.rdf"); target.create(target.NORMAL_FILE_TYPE, 0644); var stream = Components.classes["@mozilla.org/network/file-output-stream;1"] - .createInstance(Components.interfaces.nsIFileOutputStream); + .createInstance(Ci.nsIFileOutputStream); stream.init(target, 0x04 | 0x08 | 0x20, 0664, 0); // write, create, truncate stream.write(installrdf, installrdf.length); stream.close(); @@ -506,7 +509,7 @@ function check_state(test, lastTest, callback) { function load_blocklist(file) { Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:4444/data/" + file); var blocklist = Components.classes["@mozilla.org/extensions/blocklist;1"] - .getService(Components.interfaces.nsITimerCallback); + .getService(Ci.nsITimerCallback); blocklist.notify(null); } @@ -521,7 +524,7 @@ function run_test() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); startupManager(); - gTestserver = new nsHttpServer(); + gTestserver = new HttpServer(); gTestserver.registerDirectory("/data/", do_get_file("data")); gTestserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug455906.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug455906.js index 2da462a8c2bd..76917d1c5ed2 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug455906.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug455906.js @@ -8,7 +8,11 @@ const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/bloc const PREF_BLOCKLIST_ITEM_URL = "extensions.blocklist.itemURL"; Services.prefs.setCharPref(PREF_BLOCKLIST_ITEM_URL, "http://localhost:4444/blocklist/%blockID%"); -do_load_httpd_js(); +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; + +Cu.import("resource://testing-common/httpd.js"); var ADDONS = [{ // Tests how the blocklist affects a disabled add-on @@ -247,7 +251,7 @@ function run_test() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); startupManager(); - gTestserver = new nsHttpServer(); + gTestserver = new HttpServer(); gTestserver.registerDirectory("/data/", do_get_file("data")); gTestserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1.js index 4cbf286d3cae..a726dd6c4303 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1.js @@ -15,14 +15,14 @@ var ADDONS = [ "test_bug470377_5", ]; -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var server; function run_test() { do_test_pending(); createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2"); - server = new nsHttpServer(); + server = new HttpServer(); server.registerDirectory("/", do_get_file("data/test_bug470377")); server.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1_strictcompat.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1_strictcompat.js index 2364d81ede03..c490745e807d 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1_strictcompat.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1_strictcompat.js @@ -15,14 +15,14 @@ var ADDONS = [ "test_bug470377_5", ]; -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var server; function run_test() { do_test_pending(); createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2"); - server = new nsHttpServer(); + server = new HttpServer(); server.registerDirectory("/", do_get_file("data/test_bug470377")); server.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_2.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_2.js index 81ce4de2c003..59c6baf50e9a 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_2.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_2.js @@ -29,14 +29,14 @@ var ADDONS = [ "test_bug470377_5", ]; -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var server; function run_test() { do_test_pending(); createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2"); - server = new nsHttpServer(); + server = new HttpServer(); server.registerDirectory("/", do_get_file("data/test_bug470377")); server.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug514327_3.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug514327_3.js index 7511a3fcb3f0..6e415f600f5b 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug514327_3.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug514327_3.js @@ -2,8 +2,11 @@ * 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/. */ -do_load_httpd_js(); +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; +Cu.import("resource://testing-common/httpd.js"); const nsIBLS = Ci.nsIBlocklistService; const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul"; @@ -105,15 +108,15 @@ registrar.registerFactory(Components.ID("{1dfeb90a-2193-45d5-9cb8-864928b2af55}" function do_update_blocklist(aDatafile, aNextPart) { gNextTestPart = aNextPart; - + gPrefs.setCharPref("extensions.blocklist.url", "http://localhost:4444/data/" + aDatafile); gBlocklist.QueryInterface(Ci.nsITimerCallback).notify(null); } function run_test() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9"); - - gTestserver = new nsHttpServer(); + + gTestserver = new HttpServer(); gTestserver.registerDirectory("/data/", do_get_file("data")); gTestserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug542391.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug542391.js index 8954bff74c47..755e918ca2fa 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug542391.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug542391.js @@ -9,7 +9,11 @@ const PREF_EM_SHOW_MISMATCH_UI = "extensions.showMismatchUI"; // The test extension uses an insecure update url. Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); -do_load_httpd_js(); +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; + +Cu.import("resource://testing-common/httpd.js"); var testserver; const profileDir = gProfD.clone(); @@ -302,7 +306,7 @@ function run_test() { }, profileDir); // Create and configure the HTTP server. - testserver = new nsHttpServer(); + testserver = new HttpServer(); testserver.registerDirectory("/data/", do_get_file("data")); testserver.registerDirectory("/addons/", do_get_file("addons")); testserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug554133.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug554133.js index dc1d857ba9ad..f2522fdb9813 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug554133.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug554133.js @@ -9,7 +9,7 @@ Components.utils.import("resource://gre/modules/AddonRepository.jsm"); const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url"; -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var server; var TESTS = [ @@ -69,7 +69,7 @@ function run_test() startupManager(); - server = new nsHttpServer(); + server = new HttpServer(); server.registerDirectory("/", do_get_file("data")); server.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug570173.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug570173.js index 748355fad644..db3fc1c5a567 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug570173.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug570173.js @@ -7,7 +7,7 @@ // The test extension uses an insecure update url. Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var testserver; const profileDir = gProfD.clone(); profileDir.append("extensions"); @@ -16,7 +16,7 @@ function run_test() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); // Create and configure the HTTP server. - testserver = new nsHttpServer(); + testserver = new HttpServer(); testserver.registerDirectory("/data/", do_get_file("data")); testserver.registerDirectory("/addons/", do_get_file("addons")); testserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug619730.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug619730.js index a55735787f96..9c747b03640f 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug619730.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug619730.js @@ -3,7 +3,11 @@ */ // Tests whether -do_load_httpd_js(); +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; + +Cu.import("resource://testing-common/httpd.js"); var gTestserver = null; @@ -22,7 +26,7 @@ function run_test() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); startupManager(); - gTestserver = new nsHttpServer(); + gTestserver = new HttpServer(); gTestserver.registerDirectory("/data/", do_get_file("data")); gTestserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug620837.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug620837.js index 162c7c6beb1e..9400d7b7cdb0 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug620837.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug620837.js @@ -2,7 +2,7 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); const PREF_BLOCKLIST_LASTUPDATETIME = "app.update.lastUpdateTime.blocklist-background-update-timer"; const PREF_BLOCKLIST_PINGCOUNTTOTAL = "extensions.blocklist.pingCountTotal"; @@ -28,7 +28,7 @@ function pathHandler(metadata, response) { function run_test() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); - gTestserver = new nsHttpServer(); + gTestserver = new HttpServer(); gTestserver.registerPathHandler("/", pathHandler); gTestserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug655254.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug655254.js index 713ee5fda452..364e56088796 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_bug655254.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug655254.js @@ -13,7 +13,7 @@ Services.prefs.setIntPref("extensions.enabledScopes", createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "1.9.2"); -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var testserver; var userDir = gProfD.clone(); @@ -50,7 +50,7 @@ function run_test() { do_test_pending(); // Create and configure the HTTP server. - testserver = new nsHttpServer(); + testserver = new HttpServer(); testserver.registerDirectory("/data/", do_get_file("data")); testserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_compatoverrides.js b/toolkit/mozapps/extensions/test/xpcshell/test_compatoverrides.js index a52b370811d5..4b31c5e0b0a7 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_compatoverrides.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_compatoverrides.js @@ -18,7 +18,7 @@ Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true); Services.prefs.setCharPref(PREF_GETADDONS_BYIDS, BASE_URL + REQ_URL); -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var gServer; @@ -179,7 +179,7 @@ function run_test() { writeInstallRDFForExtension(addon9, profileDir); writeInstallRDFForExtension(addon10, profileDir); - gServer = new nsHttpServer(); + gServer = new HttpServer(); gServer.registerFile(REQ_URL, do_get_file("data/test_compatoverrides.xml")); gServer.start(PORT); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_corrupt.js b/toolkit/mozapps/extensions/test/xpcshell/test_corrupt.js index a289c7393e79..643c06fd429c 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_corrupt.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_corrupt.js @@ -5,7 +5,7 @@ // Checks that we rebuild something sensible from a corrupt database -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var testserver; // The test extension uses an insecure update url. @@ -144,7 +144,7 @@ function run_test() { writeInstallRDFForExtension(theme2, profileDir); // Create and configure the HTTP server. - testserver = new nsHttpServer(); + testserver = new HttpServer(); testserver.registerDirectory("/addons/", do_get_file("addons")); testserver.registerDirectory("/data/", do_get_file("data")); testserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_corrupt_strictcompat.js b/toolkit/mozapps/extensions/test/xpcshell/test_corrupt_strictcompat.js index 648664f360bf..9db623d7ecb8 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_corrupt_strictcompat.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_corrupt_strictcompat.js @@ -5,7 +5,7 @@ // Checks that we rebuild something sensible from a corrupt database -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var testserver; // The test extension uses an insecure update url. @@ -144,7 +144,7 @@ function run_test() { writeInstallRDFForExtension(theme2, profileDir); // Create and configure the HTTP server. - testserver = new nsHttpServer(); + testserver = new HttpServer(); testserver.registerDirectory("/addons/", do_get_file("addons")); testserver.registerDirectory("/data/", do_get_file("data")); testserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_dictionary.js b/toolkit/mozapps/extensions/test/xpcshell/test_dictionary.js index 66f48be560b0..98ec20a7b987 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_dictionary.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_dictionary.js @@ -18,7 +18,7 @@ userExtDir.append("extensions2"); userExtDir.append(gAppInfo.ID); registerDirectory("XREUSysExt", userExtDir.parent); -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var testserver; /** @@ -99,7 +99,7 @@ function run_test() { do_test_pending(); // Create and configure the HTTP server. - testserver = new nsHttpServer(); + testserver = new HttpServer(); testserver.registerDirectory("/addons/", do_get_file("addons")); testserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_filepointer.js b/toolkit/mozapps/extensions/test/xpcshell/test_filepointer.js index 92d0beb78b19..38718755acbf 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_filepointer.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_filepointer.js @@ -45,7 +45,7 @@ profileDir.create(AM_Ci.nsILocalFile.DIRECTORY_TYPE, 0755); const sourceDir = gProfD.clone(); sourceDir.append("source"); -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var testserver; function writePointer(aId, aName) { @@ -70,9 +70,9 @@ function writeRelativePointer(aId, aName) { let absTarget = sourceDir.clone(); absTarget.append(do_get_expected_addon_name(aId)); - - var relTarget = absTarget.QueryInterface(Ci.nsILocalFile) - .getRelativeDescriptor(profileDir); + + var relTarget = absTarget.QueryInterface(AM_Ci.nsILocalFile) + .getRelativeDescriptor(profileDir); var fos = AM_Cc["@mozilla.org/network/file-output-stream;1"]. createInstance(AM_Ci.nsIFileOutputStream); @@ -92,7 +92,7 @@ function run_test() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1"); // Create and configure the HTTP server. - testserver = new nsHttpServer(); + testserver = new HttpServer(); testserver.registerDirectory("/data/", do_get_file("data")); testserver.registerDirectory("/addons/", do_get_file("addons")); testserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Device.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Device.js index 72de19c1c7b4..801fd38c3b78 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Device.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Device.js @@ -6,7 +6,7 @@ // exactly matches the blacklist entry, is not blocked. // Uses test_gfxBlacklist.xml -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var gTestserver = null; @@ -68,7 +68,7 @@ function run_test() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); startupManager(); - gTestserver = new nsHttpServer(); + gTestserver = new HttpServer(); gTestserver.registerDirectory("/data/", do_get_file("data")); gTestserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_DriverNew.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_DriverNew.js index ac07c2f71e9f..98b01fd8388b 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_DriverNew.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_DriverNew.js @@ -6,7 +6,7 @@ // the attributes match the blacklist entry. // Uses test_gfxBlacklist.xml -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var gTestserver = null; @@ -67,7 +67,7 @@ function run_test() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); startupManager(); - gTestserver = new nsHttpServer(); + gTestserver = new HttpServer(); gTestserver.registerDirectory("/data/", do_get_file("data")); gTestserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_DriverNew.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_DriverNew.js index 866f275f0b8d..9fa621bf4c9f 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_DriverNew.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_DriverNew.js @@ -6,7 +6,7 @@ // blacklist entry is allowed. // Uses test_gfxBlacklist.xml -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var gTestserver = null; @@ -67,7 +67,7 @@ function run_test() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); startupManager(); - gTestserver = new nsHttpServer(); + gTestserver = new HttpServer(); gTestserver.registerDirectory("/data/", do_get_file("data")); gTestserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_DriverOld.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_DriverOld.js index 9ef4984d7063..7479ddb96a20 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_DriverOld.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_DriverOld.js @@ -6,7 +6,7 @@ // blacklist entry is correctly allowed. // Uses test_gfxBlacklist.xml -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var gTestserver = null; @@ -67,7 +67,7 @@ function run_test() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); startupManager(); - gTestserver = new nsHttpServer(); + gTestserver = new HttpServer(); gTestserver.registerDirectory("/data/", do_get_file("data")); gTestserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_OK.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_OK.js index 325e37cad08d..2070fdad6a6a 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_OK.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Equal_OK.js @@ -6,7 +6,7 @@ // blacklist entry is successfully blocked. // Uses test_gfxBlacklist.xml -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var gTestserver = null; @@ -67,7 +67,7 @@ function run_test() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); startupManager(); - gTestserver = new nsHttpServer(); + gTestserver = new HttpServer(); gTestserver.registerDirectory("/data/", do_get_file("data")); gTestserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_GTE_DriverOld.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_GTE_DriverOld.js index f3dc47303a18..b209d54fb724 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_GTE_DriverOld.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_GTE_DriverOld.js @@ -6,7 +6,7 @@ // blacklist entry is allowed. // Uses test_gfxBlacklist.xml -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var gTestserver = null; @@ -67,7 +67,7 @@ function run_test() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); startupManager(); - gTestserver = new nsHttpServer(); + gTestserver = new HttpServer(); gTestserver.registerDirectory("/data/", do_get_file("data")); gTestserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_GTE_OK.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_GTE_OK.js index 79953e35ca3a..f5e0447859a9 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_GTE_OK.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_GTE_OK.js @@ -6,7 +6,7 @@ // blacklist entry is successfully blocked. // Uses test_gfxBlacklist.xml -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var gTestserver = null; @@ -67,7 +67,7 @@ function run_test() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); startupManager(); - gTestserver = new nsHttpServer(); + gTestserver = new HttpServer(); gTestserver.registerDirectory("/data/", do_get_file("data")); gTestserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_No_Comparison.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_No_Comparison.js index 7b15241900da..119f58a51e01 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_No_Comparison.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_No_Comparison.js @@ -6,7 +6,7 @@ // successfully blocked. // Uses test_gfxBlacklist.xml -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var gTestserver = null; @@ -61,7 +61,7 @@ function run_test() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); startupManager(); - gTestserver = new nsHttpServer(); + gTestserver = new HttpServer(); gTestserver.registerDirectory("/data/", do_get_file("data")); gTestserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OK.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OK.js index 18fa7286c478..91182b60ed38 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OK.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OK.js @@ -6,7 +6,7 @@ // successfully blocked. // Uses test_gfxBlacklist.xml -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var gTestserver = null; @@ -68,7 +68,7 @@ function run_test() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); startupManager(); - gTestserver = new nsHttpServer(); + gTestserver = new HttpServer(); gTestserver.registerDirectory("/data/", do_get_file("data")); gTestserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OS.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OS.js index 0f3101aa2b67..f42e27afc731 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OS.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_OS.js @@ -6,7 +6,7 @@ // exactly matches the blacklist entry, is not blocked. // Uses test_gfxBlacklist.xml -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var gTestserver = null; @@ -69,7 +69,7 @@ function run_test() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); startupManager(); - gTestserver = new nsHttpServer(); + gTestserver = new HttpServer(); gTestserver.registerDirectory("/data/", do_get_file("data")); gTestserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Vendor.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Vendor.js index ebf5d0f3dc0a..a727e859b75a 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Vendor.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_Vendor.js @@ -6,7 +6,7 @@ // exactly matches the blacklist entry, is not blocked. // Uses test_gfxBlacklist.xml -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var gTestserver = null; @@ -68,7 +68,7 @@ function run_test() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); startupManager(); - gTestserver = new nsHttpServer(); + gTestserver = new HttpServer(); gTestserver.registerDirectory("/data/", do_get_file("data")); gTestserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_prefs.js b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_prefs.js index 24cfe14c11ce..ad4676c4d9e7 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_prefs.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gfxBlacklist_prefs.js @@ -6,7 +6,7 @@ // its decisions when the remote blacklist is changed. // Uses test_gfxBlacklist.xml and test_gfxBlacklist2.xml -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var gTestserver = null; @@ -68,7 +68,7 @@ function run_test() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "3", "8"); startupManager(); - gTestserver = new nsHttpServer(); + gTestserver = new HttpServer(); gTestserver.registerDirectory("/data/", do_get_file("data")); gTestserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_hotfix.js b/toolkit/mozapps/extensions/test/xpcshell/test_hotfix.js index c082c2c83c82..b57e4126546b 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_hotfix.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_hotfix.js @@ -9,7 +9,7 @@ Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); // Ignore any certificate requirements the app has set Services.prefs.setBoolPref("extensions.hotfix.cert.checkAttributes", false); -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var testserver; const profileDir = gProfD.clone(); profileDir.append("extensions"); @@ -18,7 +18,7 @@ function run_test() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); // Create and configure the HTTP server. - testserver = new nsHttpServer(); + testserver = new HttpServer(); testserver.registerDirectory("/data/", do_get_file("data")); testserver.registerDirectory("/addons/", do_get_file("addons")); testserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_install.js b/toolkit/mozapps/extensions/test/xpcshell/test_install.js index bcc153a673a0..672b20adf1fe 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_install.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_install.js @@ -3,19 +3,22 @@ */ // This verifies that add-ons can be installed from XPI files +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; // Maximum error in file modification times. Some file systems don't store // modification times exactly. As long as we are closer than this then it // still passes. const MAX_TIME_DIFFERENCE = 3000; -Components.utils.import("resource://gre/modules/Services.jsm"); -Components.utils.import("resource://gre/modules/NetUtil.jsm"); - // install.rdf size, icon.png, icon64.png size const ADDON1_SIZE = 705 + 16 + 16; -do_load_httpd_js(); +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); +Cu.import("resource://testing-common/httpd.js"); + var testserver; var gInstallDate; var gInstall = null; @@ -38,7 +41,7 @@ function run_test() { AddonManager.addAddonListener(AddonListener); // Create and configure the HTTP server. - testserver = new nsHttpServer(); + testserver = new HttpServer(); testserver.registerDirectory("/addons/", do_get_file("addons")); testserver.registerDirectory("/data/", do_get_file("data")); testserver.registerPathHandler("/redirect", function(aRequest, aResponse) { diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_install_strictcompat.js b/toolkit/mozapps/extensions/test/xpcshell/test_install_strictcompat.js index 4c0f7a4bf026..fa89174ba7d6 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_install_strictcompat.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_install_strictcompat.js @@ -3,19 +3,22 @@ */ // This verifies that add-ons can be installed from XPI files +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; // Maximum error in file modification times. Some file systems don't store // modification times exactly. As long as we are closer than this then it // still passes. const MAX_TIME_DIFFERENCE = 3000; -Components.utils.import("resource://gre/modules/Services.jsm"); -Components.utils.import("resource://gre/modules/NetUtil.jsm"); - // install.rdf size, icon.png, icon64.png size const ADDON1_SIZE = 705 + 16 + 16; -do_load_httpd_js(); +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); +Cu.import("resource://testing-common/httpd.js"); + var testserver; var gInstallDate; var gInstall = null; @@ -39,7 +42,7 @@ function run_test() { AddonManager.addAddonListener(AddonListener); // Create and configure the HTTP server. - testserver = new nsHttpServer(); + testserver = new HttpServer(); testserver.registerDirectory("/addons/", do_get_file("addons")); testserver.registerDirectory("/data/", do_get_file("data")); testserver.registerPathHandler("/redirect", function(aRequest, aResponse) { diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_locked.js b/toolkit/mozapps/extensions/test/xpcshell/test_locked.js index 48e1f79f3df4..c81613733fdb 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_locked.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_locked.js @@ -5,7 +5,7 @@ // Checks that we rebuild something sensible from a corrupt database -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var testserver; // The test extension uses an insecure update url. @@ -144,7 +144,7 @@ function run_test() { writeInstallRDFForExtension(theme2, profileDir); // Create and configure the HTTP server. - testserver = new nsHttpServer(); + testserver = new HttpServer(); testserver.registerDirectory("/addons/", do_get_file("addons")); testserver.registerDirectory("/data/", do_get_file("data")); testserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_locked_strictcompat.js b/toolkit/mozapps/extensions/test/xpcshell/test_locked_strictcompat.js index 42d694ecc753..12555c8bba0f 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_locked_strictcompat.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_locked_strictcompat.js @@ -5,7 +5,7 @@ // Checks that we rebuild something sensible from a corrupt database -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var testserver; // The test extension uses an insecure update url. @@ -144,7 +144,7 @@ function run_test() { writeInstallRDFForExtension(theme2, profileDir); // Create and configure the HTTP server. - testserver = new nsHttpServer(); + testserver = new HttpServer(); testserver.registerDirectory("/addons/", do_get_file("addons")); testserver.registerDirectory("/data/", do_get_file("data")); testserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_migrate4.js b/toolkit/mozapps/extensions/test/xpcshell/test_migrate4.js index fa3551b3d548..5c3464456975 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_migrate4.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_migrate4.js @@ -91,7 +91,7 @@ var defaultTheme = { const profileDir = gProfD.clone(); profileDir.append("extensions"); -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var testserver; let oldSyncGUIDs = {}; @@ -100,7 +100,7 @@ function prepare_profile() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); // Create and configure the HTTP server. - testserver = new nsHttpServer(); + testserver = new HttpServer(); testserver.registerDirectory("/data/", do_get_file("data")); testserver.registerDirectory("/addons/", do_get_file("addons")); testserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_update.js b/toolkit/mozapps/extensions/test/xpcshell/test_update.js index 29e27e73ff5e..0ca5e29ba51b 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_update.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_update.js @@ -24,7 +24,7 @@ const PARAMS = "?%REQ_VERSION%/%ITEM_ID%/%ITEM_VERSION%/%ITEM_MAXAPPVERSION%/" + var gInstallDate; -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var testserver; const profileDir = gProfD.clone(); profileDir.append("extensions"); @@ -37,7 +37,7 @@ function run_test() { Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "fr-FR"); // Create and configure the HTTP server. - testserver = new nsHttpServer(); + testserver = new HttpServer(); testserver.registerDirectory("/data/", do_get_file("data")); testserver.registerDirectory("/addons/", do_get_file("addons")); testserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_update_compatmode.js b/toolkit/mozapps/extensions/test/xpcshell/test_update_compatmode.js index b4024e192646..8842fdc109c4 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_update_compatmode.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_update_compatmode.js @@ -9,7 +9,7 @@ // The test extension uses an insecure update url. Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var testserver; const profileDir = gProfD.clone(); profileDir.append("extensions"); @@ -30,11 +30,11 @@ function run_test() { var version = "nightly"; } else { version = Services.appinfo.version.replace(/^([^\.]+\.[0-9]+[a-z]*).*/gi, "$1"); - } + } COMPATIBILITY_PREF = "extensions.checkCompatibility." + version; // Create and configure the HTTP server. - testserver = new nsHttpServer(); + testserver = new HttpServer(); testserver.registerDirectory("/data/", do_get_file("data")); testserver.registerDirectory("/addons/", do_get_file("addons")); testserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_update_ignorecompat.js b/toolkit/mozapps/extensions/test/xpcshell/test_update_ignorecompat.js index 82ebd925edfd..9c72d07adf4f 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_update_ignorecompat.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_update_ignorecompat.js @@ -11,7 +11,7 @@ const PREF_GETADDONS_CACHE_ENABLED = "extensions.getAddons.cache.enabled"; // The test extension uses an insecure update url. Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var testserver; const profileDir = gProfD.clone(); profileDir.append("extensions"); @@ -21,7 +21,7 @@ function run_test() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); // Create and configure the HTTP server. - testserver = new nsHttpServer(); + testserver = new HttpServer(); testserver.registerDirectory("/data/", do_get_file("data")); testserver.registerDirectory("/addons/", do_get_file("addons")); testserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_update_strictcompat.js b/toolkit/mozapps/extensions/test/xpcshell/test_update_strictcompat.js index df56708cb051..37ea258074e8 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_update_strictcompat.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_update_strictcompat.js @@ -23,7 +23,7 @@ const PARAMS = "?%REQ_VERSION%/%ITEM_ID%/%ITEM_VERSION%/%ITEM_MAXAPPVERSION%/" + var gInstallDate; -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var testserver; const profileDir = gProfD.clone(); profileDir.append("extensions"); @@ -35,7 +35,7 @@ function run_test() { Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, true); // Create and configure the HTTP server. - testserver = new nsHttpServer(); + testserver = new HttpServer(); testserver.registerDirectory("/data/", do_get_file("data")); testserver.registerDirectory("/addons/", do_get_file("addons")); testserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_updatecheck.js b/toolkit/mozapps/extensions/test/xpcshell/test_updatecheck.js index f3b9b34b1ab9..0cea7c5251dc 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_updatecheck.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_updatecheck.js @@ -8,7 +8,7 @@ Components.utils.import("resource://gre/modules/AddonUpdateChecker.jsm"); var COMPATIBILITY_PREF; -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var testserver; function run_test() { @@ -25,7 +25,7 @@ function run_test() { COMPATIBILITY_PREF = "extensions.checkCompatibility." + version; // Create and configure the HTTP server. - testserver = new nsHttpServer(); + testserver = new HttpServer(); testserver.registerDirectory("/data/", do_get_file("data")); testserver.start(4444); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_updateid.js b/toolkit/mozapps/extensions/test/xpcshell/test_updateid.js index dd54ea4b09b7..6af720bf9cfc 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_updateid.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_updateid.js @@ -7,7 +7,7 @@ // The test extension uses an insecure update url. Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); -do_load_httpd_js(); +Components.utils.import("resource://testing-common/httpd.js"); var testserver; const profileDir = gProfD.clone(); profileDir.append("extensions"); @@ -33,7 +33,7 @@ function run_test() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); // Create and configure the HTTP server. - testserver = new nsHttpServer(); + testserver = new HttpServer(); testserver.registerDirectory("/data/", do_get_file("data")); testserver.registerDirectory("/addons/", do_get_file("addons")); testserver.start(4444); From 8c13f6d202ef180f8e2ad5957a6e6939a6145312 Mon Sep 17 00:00:00 2001 From: Jason Duell <jduell.mcbugs@gmail.com> Date: Tue, 7 Aug 2012 22:09:28 -0700 Subject: [PATCH 128/169] Bug 780818 - Remove getExtendedOrigin from nsILoadContext. r=smaug, sr=sicking --- docshell/base/LoadContext.cpp | 10 ---------- docshell/base/nsDocShell.cpp | 14 -------------- docshell/base/nsDocShell.h | 1 - docshell/base/nsILoadContext.idl | 18 +----------------- netwerk/base/public/nsNetUtil.h | 21 --------------------- 5 files changed, 1 insertion(+), 63 deletions(-) diff --git a/docshell/base/LoadContext.cpp b/docshell/base/LoadContext.cpp index c8512ce2da26..12db107ea77b 100644 --- a/docshell/base/LoadContext.cpp +++ b/docshell/base/LoadContext.cpp @@ -97,14 +97,4 @@ LoadContext::GetAppId(PRUint32* aAppId) return NS_OK; } -NS_IMETHODIMP -LoadContext::GetExtendedOrigin(nsIURI* aUri, nsACString& aResult) -{ - MOZ_ASSERT(mIsNotNull); - - nsIScriptSecurityManager* ssmgr = nsContentUtils::GetSecurityManager(); - - return ssmgr->GetExtendedOrigin(aUri, mAppId, mIsInBrowserElement, aResult); -} - } // namespace mozilla diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 48fb2dc07230..8e58874c0277 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -11395,20 +11395,6 @@ nsDocShell::GetIsContent(bool *aIsContent) return NS_OK; } -NS_IMETHODIMP -nsDocShell::GetExtendedOrigin(nsIURI *aUri, nsACString &aResult) -{ - bool isInBrowserElement; - GetIsInBrowserElement(&isInBrowserElement); - - nsCOMPtr<nsIScriptSecurityManager> ssmgr = - do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID); - NS_ENSURE_TRUE(ssmgr, NS_ERROR_FAILURE); - - return ssmgr->GetExtendedOrigin(aUri, mAppId, isInBrowserElement, aResult); -} - - bool nsDocShell::IsOKToLoadURI(nsIURI* aURI) { diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h index 87ac0a0d9406..2b8d12856377 100644 --- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -228,7 +228,6 @@ public: NS_IMETHOD GetIsContent(bool*); NS_IMETHOD GetUsePrivateBrowsing(bool*); NS_IMETHOD SetUsePrivateBrowsing(bool); - NS_IMETHOD GetExtendedOrigin(nsIURI *uri, nsACString & retval); // Restores a cached presentation from history (mLSHE). // This method swaps out the content viewer and simulates loads for diff --git a/docshell/base/nsILoadContext.idl b/docshell/base/nsILoadContext.idl index b899261d285f..37d73f80550b 100644 --- a/docshell/base/nsILoadContext.idl +++ b/docshell/base/nsILoadContext.idl @@ -7,14 +7,13 @@ #include "nsISupports.idl" interface nsIDOMWindow; -interface nsIURI; /** * An nsILoadContext represents the context of a load. This interface * can be queried for various information about where the load is * happening. */ -[scriptable, uuid(386806c3-c4cb-4b3d-b05d-c08ea10f5585)] +[scriptable, uuid(48b5bf16-e0c7-11e1-b28e-91726188709b)] interface nsILoadContext : nsISupports { /** @@ -79,19 +78,4 @@ interface nsILoadContext : nsISupports */ readonly attribute unsigned long appId; - /** - * Get the extended origin of a channel in this load context. - * The extended origin is a string that has more information than the origin - * and can be used to isolate data or permissions between different - * principals while taking into account parameters like the app id or the - * fact that the load is taking place in a mozbrowser. - * - * In some cases this function will simply return the origin for the - * channel's URI. - * - * The extendedOrigin is intended to be an opaque identifier. It is - * currently "human-readable" but no callers should assume it will stay - * as-is and it might be crypto-hashed at some point. - */ - AUTF8String GetExtendedOrigin(in nsIURI channel); }; diff --git a/netwerk/base/public/nsNetUtil.h b/netwerk/base/public/nsNetUtil.h index 569301bbdc06..8af2d437c6ed 100644 --- a/netwerk/base/public/nsNetUtil.h +++ b/netwerk/base/public/nsNetUtil.h @@ -1330,27 +1330,6 @@ NS_UsePrivateBrowsing(nsIChannel *channel) return loadContext && loadContext->UsePrivateBrowsing(); } -/** - * Gets ExtendedOrigin value for given channel's nsILoadContext. - * Returns false if error or channel's callbacks don't implement nsILoadContext. - */ -inline bool -NS_GetExtendedOrigin(nsIChannel *aChannel, nsACString &aResult) -{ - nsCOMPtr<nsILoadContext> loadContext; - NS_QueryNotificationCallbacks(aChannel, loadContext); - if (!loadContext) { - return false; - } - nsCOMPtr<nsIURI> uri; - nsresult rv = aChannel->GetURI(getter_AddRefs(uri)); - NS_ENSURE_SUCCESS(rv, false); - - rv = loadContext->GetExtendedOrigin(uri, aResult); - NS_ENSURE_SUCCESS(rv, false); - return true; -} - /** * Gets AppId and isInBrowserElement from channel's nsILoadContext. * Returns false if error or channel's callbacks don't implement nsILoadContext. From aa790aa109d58120d3164c036110c627e6adf8f5 Mon Sep 17 00:00:00 2001 From: Phil Ringnalda <philringnalda@gmail.com> Date: Tue, 7 Aug 2012 22:18:27 -0700 Subject: [PATCH 129/169] Backout 5439489dc320, 983f76488e59, 7a92558a8dec (Bug 714358) for debug build assertions and leaks --- b2g/installer/package-manifest.in | 1 - content/base/src/nsGkAtomList.h | 1 - content/events/public/nsEventNameList.h | 4 - content/events/src/nsDOMEvent.cpp | 3 +- content/events/src/nsDOMEvent.h | 3 +- content/events/src/nsEventListenerManager.cpp | 32 +------ content/events/src/nsEventListenerManager.h | 3 - dom/Makefile.in | 1 - dom/base/Navigator.cpp | 57 ++++-------- dom/base/Navigator.h | 9 -- dom/base/nsDOMClassInfo.cpp | 9 -- dom/base/nsDOMClassInfoClasses.h | 2 - dom/base/nsGlobalWindow.cpp | 14 --- dom/base/nsGlobalWindow.h | 3 - dom/base/nsPIDOMWindow.h | 3 - dom/dom-config.mk | 1 - dom/interfaces/base/nsIDOMWindow.idl | 3 +- dom/time/Makefile.in | 35 -------- dom/time/TimeChangeObserver.cpp | 87 ------------------- dom/time/TimeChangeObserver.h | 29 ------- dom/time/TimeManager.cpp | 57 ------------ dom/time/TimeManager.h | 31 ------- dom/time/nsIDOMNavigatorTime.idl | 13 --- dom/time/nsIDOMTimeManager.idl | 20 ----- hal/Hal.cpp | 21 ----- hal/Hal.h | 20 ----- hal/HalTypes.h | 18 +--- hal/gonk/GonkHal.cpp | 24 +---- hal/sandbox/PHal.ipdl | 2 - hal/sandbox/SandboxHal.cpp | 11 --- layout/build/Makefile.in | 1 - toolkit/toolkit-makefiles.sh | 1 - widget/nsGUIEvent.h | 3 - 33 files changed, 21 insertions(+), 501 deletions(-) delete mode 100644 dom/time/Makefile.in delete mode 100644 dom/time/TimeChangeObserver.cpp delete mode 100644 dom/time/TimeChangeObserver.h delete mode 100644 dom/time/TimeManager.cpp delete mode 100644 dom/time/TimeManager.h delete mode 100644 dom/time/nsIDOMNavigatorTime.idl delete mode 100644 dom/time/nsIDOMTimeManager.idl diff --git a/b2g/installer/package-manifest.in b/b2g/installer/package-manifest.in index 79071a967efa..097717e73e5a 100644 --- a/b2g/installer/package-manifest.in +++ b/b2g/installer/package-manifest.in @@ -201,7 +201,6 @@ @BINPATH@/components/dom_xpath.xpt @BINPATH@/components/dom_xul.xpt @BINPATH@/components/dom_loadsave.xpt -@BINPATH@/components/dom_time.xpt @BINPATH@/components/downloads.xpt @BINPATH@/components/editor.xpt @BINPATH@/components/embed_base.xpt diff --git a/content/base/src/nsGkAtomList.h b/content/base/src/nsGkAtomList.h index 82f010b68a80..0b4613cfa803 100644 --- a/content/base/src/nsGkAtomList.h +++ b/content/base/src/nsGkAtomList.h @@ -684,7 +684,6 @@ GK_ATOM(onmozfullscreenchange, "onmozfullscreenchange") GK_ATOM(onmozfullscreenerror, "onmozfullscreenerror") GK_ATOM(onmozpointerlockchange, "onmozpointerlockchange") GK_ATOM(onmozpointerlockerror, "onmozpointerlockerror") -GK_ATOM(onmoztimechange, "onmoztimechange") GK_ATOM(onMozMousePixelScroll, "onMozMousePixelScroll") GK_ATOM(onMozScrolledAreaChanged, "onMozScrolledAreaChanged") GK_ATOM(ononline, "ononline") diff --git a/content/events/public/nsEventNameList.h b/content/events/public/nsEventNameList.h index 28d65df9f4ca..10e7f68fe428 100644 --- a/content/events/public/nsEventNameList.h +++ b/content/events/public/nsEventNameList.h @@ -435,10 +435,6 @@ WINDOW_ONLY_EVENT(devicelight, NS_DEVICE_LIGHT, EventNameType_None, NS_EVENT) -WINDOW_ONLY_EVENT(moztimechange, - NS_MOZ_TIME_CHANGE_EVENT, - EventNameType_None, - NS_EVENT) TOUCH_EVENT(touchstart, NS_TOUCH_START, diff --git a/content/events/src/nsDOMEvent.cpp b/content/events/src/nsDOMEvent.cpp index 4f51b888bf8a..f542a6b67dd7 100644 --- a/content/events/src/nsDOMEvent.cpp +++ b/content/events/src/nsDOMEvent.cpp @@ -97,8 +97,7 @@ static const char* const sEventNames[] = { "deviceorientation", "deviceproximity", "userproximity", - "devicelight", - "moztimechange" + "devicelight" }; static char *sPopupAllowedEvents; diff --git a/content/events/src/nsDOMEvent.h b/content/events/src/nsDOMEvent.h index 5381ed0707cf..c01d57b56b90 100644 --- a/content/events/src/nsDOMEvent.h +++ b/content/events/src/nsDOMEvent.h @@ -177,8 +177,7 @@ public: eDOMEvents_deviceorientation, eDOMEvents_deviceproximity, eDOMEvents_userproximity, - eDOMEvents_devicelight, - eDOMEvents_moztimechange + eDOMEvents_devicelight }; nsDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent); diff --git a/content/events/src/nsEventListenerManager.cpp b/content/events/src/nsEventListenerManager.cpp index 1150ff4e6533..78697870fded 100644 --- a/content/events/src/nsEventListenerManager.cpp +++ b/content/events/src/nsEventListenerManager.cpp @@ -53,7 +53,6 @@ #include "nsIContentSecurityPolicy.h" #include "nsJSEnvironment.h" #include "xpcpublic.h" -#include "TimeChangeObserver.h" using namespace mozilla::dom; using namespace mozilla::hal; @@ -272,8 +271,6 @@ nsEventListenerManager::AddEventListener(nsIDOMEventListener *aListener, EnableDevice(NS_DEVICE_LIGHT); } else if (aTypeAtom == nsGkAtoms::ondevicemotion) { EnableDevice(NS_DEVICE_MOTION); - } else if (aTypeAtom == nsGkAtoms::onmoztimechange) { - EnableTimeChangeNotifications(); } else if ((aType >= NS_MOZTOUCH_DOWN && aType <= NS_MOZTOUCH_UP) || (aTypeAtom == nsGkAtoms::ontouchstart || aTypeAtom == nsGkAtoms::ontouchend || @@ -399,7 +396,6 @@ nsEventListenerManager::RemoveEventListener(nsIDOMEventListener *aListener, PRUint32 count = mListeners.Length(); PRUint32 typeCount = 0; bool deviceType = IsDeviceType(aType); - bool timeChangeEvent = (aType == NS_MOZ_TIME_CHANGE_EVENT); for (PRUint32 i = 0; i < count; ++i) { ls = &mListeners.ElementAt(i); @@ -413,7 +409,7 @@ nsEventListenerManager::RemoveEventListener(nsIDOMEventListener *aListener, mNoListenerForEvent = NS_EVENT_TYPE_NULL; mNoListenerForEventAtom = nullptr; - if (!deviceType && !timeChangeEvent) { + if (!deviceType) { return; } --typeCount; @@ -423,8 +419,6 @@ nsEventListenerManager::RemoveEventListener(nsIDOMEventListener *aListener, if (deviceType && typeCount == 0) { DisableDevice(aType); - } else if (timeChangeEvent && typeCount == 0) { - DisableTimeChangeNotifications(); } } @@ -1115,27 +1109,3 @@ nsEventListenerManager::UnmarkGrayJSListeners() } } } - -void -nsEventListenerManager::EnableTimeChangeNotifications() -{ - nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(mTarget); - if (!window) { - return; - } - - NS_ASSERTION(window->IsInnerWindow(), "Target should not be an outer window"); - window->EnableTimeChangeNotifications(); -} - -void -nsEventListenerManager::DisableTimeChangeNotifications() -{ - nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(mTarget); - if (!window) { - return; - } - - NS_ASSERTION(window->IsInnerWindow(), "Target should not be an outer window"); - window->DisableTimeChangeNotifications(); -} diff --git a/content/events/src/nsEventListenerManager.h b/content/events/src/nsEventListenerManager.h index 4635b3be9bf8..f77289920d96 100644 --- a/content/events/src/nsEventListenerManager.h +++ b/content/events/src/nsEventListenerManager.h @@ -261,9 +261,6 @@ protected: void EnableDevice(PRUint32 aType); void DisableDevice(PRUint32 aType); - void EnableTimeChangeNotifications(); - void DisableTimeChangeNotifications(); - public: /** * Set the "inline" event listener for aEventName to |v|. This diff --git a/dom/Makefile.in b/dom/Makefile.in index 80ad3d41a166..c210af5a9c8a 100644 --- a/dom/Makefile.in +++ b/dom/Makefile.in @@ -61,7 +61,6 @@ DIRS += \ sms \ mms \ src \ - time \ locales \ network \ plugins/base \ diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index a0c1ecd1393e..a8435f7ee0c7 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -38,7 +38,6 @@ #include "Connection.h" #include "MobileConnection.h" #include "nsIIdleObserver.h" -#include "TimeManager.h" #ifdef MOZ_MEDIA_NAVIGATOR #include "MediaManager.h" @@ -116,7 +115,6 @@ NS_INTERFACE_MAP_BEGIN(Navigator) #endif NS_INTERFACE_MAP_ENTRY(nsIDOMNavigatorCamera) NS_INTERFACE_MAP_ENTRY(nsIDOMNavigatorSystemMessages) - NS_INTERFACE_MAP_ENTRY(nsIDOMMozNavigatorTime) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Navigator) NS_INTERFACE_MAP_END @@ -199,9 +197,6 @@ Navigator::Invalidate() } mDeviceStorageStores.Clear(); - if (mTimeManager) { - mTimeManager = nsnull; - } } nsPIDOMWindow * @@ -1246,9 +1241,21 @@ Navigator::GetMozMobileConnection(nsIDOMMozMobileConnection** aMobileConnection) if (!mMobileConnection) { nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow); - if (!CheckPermission("dom.mobileconnection.whitelist")) { - return NS_OK; - } + NS_ENSURE_TRUE(window && window->GetDocShell(), NS_OK); + + // Chrome is always allowed access, so do the permission check only + // for non-chrome pages. + if (!nsContentUtils::IsCallerChrome()) { + nsCOMPtr<nsIDocument> doc = do_QueryInterface(window->GetExtantDocument()); + NS_ENSURE_TRUE(doc, NS_OK); + + nsCOMPtr<nsIURI> uri; + doc->NodePrincipal()->GetURI(getter_AddRefs(uri)); + + if (!nsContentUtils::URIIsChromeOrInPref(uri, "dom.mobileconnection.whitelist")) { + return NS_OK; + } + } mMobileConnection = new network::MobileConnection(); mMobileConnection->Init(window); @@ -1344,25 +1351,6 @@ Navigator::MozSetMessageHandler(const nsAString& aType, #endif } -//***************************************************************************** -// Navigator::nsIDOMNavigatorTime -//***************************************************************************** -NS_IMETHODIMP -Navigator::GetMozTime(nsIDOMMozTimeManager** aTime) -{ - if (!CheckPermission("dom.time.whitelist")) { - return NS_ERROR_DOM_SECURITY_ERR; - } - - if (!mTimeManager) { - *aTime = nsnull; - mTimeManager = new time::TimeManager(); - } - - NS_ADDREF(*aTime = mTimeManager); - return NS_OK; -} - //***************************************************************************** // nsNavigator::nsIDOMNavigatorCamera //***************************************************************************** @@ -1426,21 +1414,6 @@ Navigator::OnNavigation() } } -bool -Navigator::CheckPermission(const char* aPref) -{ - if (!nsContentUtils::IsCallerChrome()) { - nsCOMPtr<nsPIDOMWindow> win = do_QueryReferent(mWindow); - NS_ENSURE_TRUE(win, false); - nsCOMPtr<nsIDocument> doc = do_QueryInterface(win->GetExtantDocument()); - NS_ENSURE_TRUE(doc, false); - nsCOMPtr<nsIURI> uri; - doc->NodePrincipal()->GetURI(getter_AddRefs(uri)); - return nsContentUtils::URIIsChromeOrInPref(uri, aPref); - } - - return true; -} } // namespace dom } // namespace mozilla diff --git a/dom/base/Navigator.h b/dom/base/Navigator.h index a3c4a04ed16f..df12a3c021f0 100644 --- a/dom/base/Navigator.h +++ b/dom/base/Navigator.h @@ -15,7 +15,6 @@ #include "nsINavigatorBattery.h" #include "nsIDOMNavigatorSms.h" #include "nsIDOMNavigatorNetwork.h" -#include "nsIDOMNavigatorTime.h" #include "nsAutoPtr.h" #include "nsWeakReference.h" #include "DeviceStorage.h" @@ -70,10 +69,6 @@ namespace power { class PowerManager; } // namespace power -namespace time { -class TimeManager; -} // namespace time - class Navigator : public nsIDOMNavigator , public nsIDOMClientInformation , public nsIDOMNavigatorDeviceStorage @@ -93,7 +88,6 @@ class Navigator : public nsIDOMNavigator #endif , public nsIDOMNavigatorCamera , public nsIDOMNavigatorSystemMessages - , public nsIDOMMozNavigatorTime { public: Navigator(nsPIDOMWindow *aInnerWindow); @@ -119,7 +113,6 @@ public: NS_DECL_NSIDOMNAVIGATORBLUETOOTH #endif NS_DECL_NSIDOMNAVIGATORSYSTEMMESSAGES - NS_DECL_NSIDOMMOZNAVIGATORTIME static void Init(); @@ -151,7 +144,6 @@ public: private: bool IsSmsAllowed() const; bool IsSmsSupported() const; - bool CheckPermission(const char* aPref); nsRefPtr<nsMimeTypeArray> mMimeTypes; nsRefPtr<nsPluginArray> mPlugins; @@ -172,7 +164,6 @@ private: nsRefPtr<nsDOMCameraManager> mCameraManager; nsCOMPtr<nsIDOMNavigatorSystemMessages> mMessagesManager; nsTArray<nsRefPtr<nsDOMDeviceStorage> > mDeviceStorageStores; - nsRefPtr<time::TimeManager> mTimeManager; nsWeakPtr mWindow; }; diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index d66e10792918..c2b05fdb4d40 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -523,7 +523,6 @@ using mozilla::dom::indexedDB::IDBWrapperCache; #include "nsIDOMNavigatorSystemMessages.h" #include "mozilla/dom/Activity.h" -#include "TimeManager.h" #include "DOMCameraManager.h" #include "CameraControl.h" @@ -1699,9 +1698,6 @@ static nsDOMClassInfoData sClassInfoData[] = { EVENTTARGET_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(MozActivity, nsEventTargetSH, EVENTTARGET_SCRIPTABLE_FLAGS) - - NS_DEFINE_CLASSINFO_DATA(MozTimeManager, nsDOMGenericSH, - DOM_DEFAULT_SCRIPTABLE_FLAGS) }; // Objects that should be constructable through |new Name();| @@ -2475,7 +2471,6 @@ nsDOMClassInfo::Init() #endif DOM_CLASSINFO_MAP_ENTRY(nsIDOMNavigatorCamera) DOM_CLASSINFO_MAP_ENTRY(nsIDOMNavigatorSystemMessages) - DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozNavigatorTime) DOM_CLASSINFO_MAP_END @@ -4511,10 +4506,6 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget) DOM_CLASSINFO_MAP_END - DOM_CLASSINFO_MAP_BEGIN(MozTimeManager, nsIDOMMozTimeManager) - DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozTimeManager) - DOM_CLASSINFO_MAP_END - #ifdef DEBUG { PRUint32 i = ArrayLength(sClassInfoData); diff --git a/dom/base/nsDOMClassInfoClasses.h b/dom/base/nsDOMClassInfoClasses.h index 9e857f22bad9..c587c2c12e76 100644 --- a/dom/base/nsDOMClassInfoClasses.h +++ b/dom/base/nsDOMClassInfoClasses.h @@ -538,5 +538,3 @@ DOMCI_CLASS(FileRequest) DOMCI_CLASS(LockedFile) DOMCI_CLASS(MozActivity) - -DOMCI_CLASS(MozTimeManager) diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 017707faf788..8eb091e4bd40 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -222,7 +222,6 @@ #include "nsDOMEventTargetHelper.h" #include "nsIAppsService.h" #include "prrng.h" -#include "TimeChangeObserver.h" #ifdef ANDROID #include <android/log.h> @@ -1056,7 +1055,6 @@ nsGlobalWindow::CleanUp(bool aIgnoreModalDialog) mIdleTimer = nullptr; } - DisableTimeChangeNotifications(); #ifdef DEBUG nsCycleCollector_DEBUG_shouldBeFreed(static_cast<nsIScriptGlobalObject*>(this)); #endif @@ -10622,18 +10620,6 @@ nsGlobalWindow::GetURL(nsIDOMMozURLProperty** aURL) return NS_OK; } -void -nsGlobalWindow::EnableTimeChangeNotifications() -{ - nsSystemTimeChangeObserver::GetInstance()->AddWindowListener(this); -} - -void -nsGlobalWindow::DisableTimeChangeNotifications() -{ - nsSystemTimeChangeObserver::GetInstance()->RemoveWindowListener(this); -} - // static bool nsGlobalWindow::HasIndexedDBSupport() diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index ad3b93b4e077..39c1deb1c95e 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -537,9 +537,6 @@ public: virtual void EnableDeviceSensor(PRUint32 aType); virtual void DisableDeviceSensor(PRUint32 aType); - virtual void EnableTimeChangeNotifications(); - virtual void DisableTimeChangeNotifications(); - virtual nsresult SetArguments(nsIArray *aArguments, nsIPrincipal *aOrigin); static bool DOMWindowDumpEnabled(); diff --git a/dom/base/nsPIDOMWindow.h b/dom/base/nsPIDOMWindow.h index 0bebde124f97..1d40ebfba0b3 100644 --- a/dom/base/nsPIDOMWindow.h +++ b/dom/base/nsPIDOMWindow.h @@ -576,9 +576,6 @@ public: */ virtual void DisableDeviceSensor(PRUint32 aType) = 0; - virtual void EnableTimeChangeNotifications() = 0; - virtual void DisableTimeChangeNotifications() = 0; - /** * Set a arguments for this window. This will be set on the window * right away (if there's an existing document) and it will also be diff --git a/dom/dom-config.mk b/dom/dom-config.mk index 135fe09d2dfc..92b372f88b0e 100644 --- a/dom/dom-config.mk +++ b/dom/dom-config.mk @@ -19,7 +19,6 @@ DOM_SRCDIRS = \ dom/src/geolocation \ dom/src/notification \ dom/workers \ - dom/time \ content/xbl/src \ content/xul/document/src \ content/events/src \ diff --git a/dom/interfaces/base/nsIDOMWindow.idl b/dom/interfaces/base/nsIDOMWindow.idl index 1d2f286c9c62..b8ce47a8bcd7 100644 --- a/dom/interfaces/base/nsIDOMWindow.idl +++ b/dom/interfaces/base/nsIDOMWindow.idl @@ -32,7 +32,7 @@ interface nsIDOMMozURLProperty : nsISupports * @see <http://www.whatwg.org/html/#window> */ -[scriptable, uuid(AB4ED3B8-84F8-4585-B413-0996A7F96D20)] +[scriptable, uuid(A1AF6CD9-C6E7-4037-99F8-DBCA1B03E345)] interface nsIDOMWindow : nsISupports { // the current browsing context @@ -496,7 +496,6 @@ interface nsIDOMWindow : nsISupports [implicit_jscontext] attribute jsval ondeviceproximity; [implicit_jscontext] attribute jsval onuserproximity; [implicit_jscontext] attribute jsval ondevicelight; - [implicit_jscontext] attribute jsval onmoztimechange; [implicit_jscontext] attribute jsval onmouseenter; [implicit_jscontext] attribute jsval onmouseleave; diff --git a/dom/time/Makefile.in b/dom/time/Makefile.in deleted file mode 100644 index 63efec4b5bdc..000000000000 --- a/dom/time/Makefile.in +++ /dev/null @@ -1,35 +0,0 @@ -# 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/. - -DEPTH = ../.. -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ - -include $(DEPTH)/config/autoconf.mk - -LIBRARY_NAME = dom_time_s -XPIDL_MODULE = dom_time -LIBXUL_LIBRARY = 1 -FORCE_STATIC_LIB = 1 - -include $(topsrcdir)/dom/dom-config.mk - -CPPSRCS = \ - TimeManager.cpp \ - TimeChangeObserver.cpp \ - $(NULL) - -EXPORTS = \ - TimeChangeObserver.h \ - $(NULL) - -XPIDLSRCS = \ - nsIDOMNavigatorTime.idl \ - nsIDOMTimeManager.idl \ - $(NULL) - -include $(topsrcdir)/config/config.mk -include $(topsrcdir)/ipc/chromium/chromium-config.mk -include $(topsrcdir)/config/rules.mk diff --git a/dom/time/TimeChangeObserver.cpp b/dom/time/TimeChangeObserver.cpp deleted file mode 100644 index 1474fc25197a..000000000000 --- a/dom/time/TimeChangeObserver.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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/. */ - -#include "TimeChangeObserver.h" -#include "mozilla/ClearOnShutdown.h" -#include "mozilla/StaticPtr.h" -#include "nsPIDOMWindow.h" -#include "nsDOMEvent.h" -#include "nsContentUtils.h" - -using namespace mozilla::hal; -using namespace mozilla; - -StaticAutoPtr<nsSystemTimeChangeObserver> sObserver; - -nsSystemTimeChangeObserver* nsSystemTimeChangeObserver::GetInstance() -{ - if (!sObserver) { - sObserver = new nsSystemTimeChangeObserver(); - ClearOnShutdown(&sObserver); - } - return sObserver; -} - -void -nsSystemTimeChangeObserver::Notify(const SystemTimeChange& aReason) -{ - //Copy mWindowListeners and iterate over windowListeners instead because - //mWindowListeners may be modified while we loop. - nsTArray<nsWeakPtr> windowListeners; - for (PRUint32 i = 0; i < mWindowListeners.Length(); i++) { - windowListeners.AppendElement(mWindowListeners.SafeElementAt(i)); - } - - for (PRInt32 i = windowListeners.Length() - 1; i >= 0; i--) { - nsCOMPtr<nsIDOMWindow> window = do_QueryReferent(windowListeners[i]); - if (!window) { - mWindowListeners.RemoveElement(windowListeners[i]); - return; - } - - nsCOMPtr<nsIDOMDocument> domdoc; - window->GetDocument(getter_AddRefs(domdoc)); - nsCOMPtr<nsIDocument> doc(do_QueryInterface(domdoc)); - if (!domdoc) { - return; - } - - nsContentUtils::DispatchTrustedEvent(doc, window, - NS_LITERAL_STRING("moztimechange"), /* bubbles = */ true, - /* canceable = */ false); - } -} - -nsresult -nsSystemTimeChangeObserver::AddWindowListener(nsIDOMWindow* aWindow) -{ - if (!aWindow) { - return NS_ERROR_ILLEGAL_VALUE; - } - - if (mWindowListeners.IndexOf(NS_GetWeakReference(aWindow)) != - nsTArray<nsIDOMWindow*>::NoIndex) { - return NS_OK; - } - - if (mWindowListeners.Length() == 0) { - RegisterSystemTimeChangeObserver(this); - } - - mWindowListeners.AppendElement(NS_GetWeakReference(aWindow)); - return NS_OK; -} - -nsresult -nsSystemTimeChangeObserver::RemoveWindowListener(nsIDOMWindow *aWindow) -{ - mWindowListeners.RemoveElement(NS_GetWeakReference(aWindow)); - - if (mWindowListeners.Length() == 0) { - UnregisterSystemTimeChangeObserver(this); - } - - return NS_OK; -} diff --git a/dom/time/TimeChangeObserver.h b/dom/time/TimeChangeObserver.h deleted file mode 100644 index 2b7c8efe1e2d..000000000000 --- a/dom/time/TimeChangeObserver.h +++ /dev/null @@ -1,29 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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/. */ - -#ifndef _mozilla_time_change_observer_h_ -#define _mozilla_time_change_observer_h_ - -#include "mozilla/Hal.h" -#include "mozilla/Observer.h" -#include "mozilla/HalTypes.h" -#include "nsPIDOMWindow.h" -#include "nsWeakPtr.h" - -typedef mozilla::Observer<mozilla::hal::SystemTimeChange> SystemTimeChangeObserver; - -class nsSystemTimeChangeObserver : public SystemTimeChangeObserver -{ -public: - static nsSystemTimeChangeObserver* GetInstance(); - void Notify(const mozilla::hal::SystemTimeChange& aReason); - nsresult AddWindowListener(nsIDOMWindow *aWindow); - nsresult RemoveWindowListener(nsIDOMWindow *aWindow); -private: - nsSystemTimeChangeObserver() {}; - nsTArray<nsWeakPtr> mWindowListeners; -}; - -#endif //_mozilla_time_change_observer_h_ diff --git a/dom/time/TimeManager.cpp b/dom/time/TimeManager.cpp deleted file mode 100644 index 227cd813b37b..000000000000 --- a/dom/time/TimeManager.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* 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/. */ -#include "jsapi.h" -#include "mozilla/Hal.h" -#include "nsDOMEvent.h" -#include "nsDOMEventTargetHelper.h" -#include "nsIDOMClassInfo.h" -#include "prtime.h" -#include "TimeManager.h" - -using namespace mozilla::hal; - -DOMCI_DATA(MozTimeManager, mozilla::dom::time::TimeManager) - -namespace mozilla { -namespace dom { -namespace time { - -NS_INTERFACE_MAP_BEGIN(TimeManager) - NS_INTERFACE_MAP_ENTRY(nsIDOMMozTimeManager) - NS_INTERFACE_MAP_ENTRY(nsISupports) - NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozTimeManager) -NS_INTERFACE_MAP_END - -NS_IMPL_ADDREF(TimeManager) -NS_IMPL_RELEASE(TimeManager) - -nsresult -TimeManager::Set(const JS::Value& date, JSContext* ctx) { - double nowMSec = JS_Now() / 1000; - double dateMSec; - - if (date.isObject()) { - JSObject* dateObj = JSVAL_TO_OBJECT(date); - - if (JS_ObjectIsDate(ctx, dateObj) && js_DateIsValid(ctx, dateObj)) { - dateMSec = js_DateGetMsecSinceEpoch(ctx, dateObj); - } - else { - NS_WARN_IF_FALSE(JS_ObjectIsDate(ctx, dateObj), "This is not a Date object"); - NS_WARN_IF_FALSE(js_DateIsValid(ctx, dateObj), "Date is not valid"); - return NS_ERROR_INVALID_ARG; - } - } else if (date.isNumber()) { - dateMSec = date.toNumber(); - } else { - return NS_ERROR_INVALID_ARG; - } - - hal::AdjustSystemClock(JS_DoubleToInt32(dateMSec - nowMSec)); - return NS_OK; -} - -} // namespace time -} // namespace dom -} // namespace mozilla diff --git a/dom/time/TimeManager.h b/dom/time/TimeManager.h deleted file mode 100644 index 8121bbde5bcd..000000000000 --- a/dom/time/TimeManager.h +++ /dev/null @@ -1,31 +0,0 @@ -/* 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/. */ - -#ifndef mozilla_dom_time_TimeManager_h -#define mozilla_dom_time_TimeManager_h - -#include "mozilla/HalTypes.h" -#include "nsIDOMTimeManager.h" -#include "mozilla/Observer.h" - -class nsPIDOMWindow; - -namespace mozilla { - -typedef Observer<hal::SystemTimeChange> SystemTimeObserver; - -namespace dom { -namespace time { -class TimeManager : public nsIDOMMozTimeManager -{ -public: - NS_DECL_ISUPPORTS - NS_DECL_NSIDOMMOZTIMEMANAGER -}; - -} // namespace time -} // namespace dom -} // namespace mozilla - -#endif //mozilla_dom_time_TimeManager_h diff --git a/dom/time/nsIDOMNavigatorTime.idl b/dom/time/nsIDOMNavigatorTime.idl deleted file mode 100644 index 49942463ed8e..000000000000 --- a/dom/time/nsIDOMNavigatorTime.idl +++ /dev/null @@ -1,13 +0,0 @@ -/* 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/. */ - -#include "nsISupports.idl" - -interface nsIDOMMozTimeManager; - -[scriptable, uuid(befc186d-c249-4acb-8e70-8080f7b45e5c)] -interface nsIDOMMozNavigatorTime : nsISupports -{ - readonly attribute nsIDOMMozTimeManager mozTime; -}; diff --git a/dom/time/nsIDOMTimeManager.idl b/dom/time/nsIDOMTimeManager.idl deleted file mode 100644 index af2f7eceaf46..000000000000 --- a/dom/time/nsIDOMTimeManager.idl +++ /dev/null @@ -1,20 +0,0 @@ -/* 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/. */ - -#include "nsISupports.idl" - -[scriptable, builtinclass, uuid(d29beaaa-bd54-4fd5-9f18-e0eedb1dc96d)] -interface nsIDOMMozTimeManager : nsISupports -{ - /* Set the system time. - * - * The |time| argument can be either a Date object or a number. - * - * - If |time| is a number, it's interpreted as seconds since the epoch - * (midnight UTC on January 1, 1970) - * - If |time| is a Date object, |set(time)| is equivalent to - * |set(time.getTime())|. - */ - [implicit_jscontext] void set(in jsval time); -}; diff --git a/hal/Hal.cpp b/hal/Hal.cpp index a52f25a27ec6..a5b6d732b142 100644 --- a/hal/Hal.cpp +++ b/hal/Hal.cpp @@ -417,28 +417,7 @@ bool GetLight(LightType light, hal::LightConfiguration* aConfig) RETURN_PROXY_IF_SANDBOXED(GetLight(light, aConfig)); } -static ObserverList<SystemTimeChange> sSystemTimeObserver; -void -RegisterSystemTimeChangeObserver(SystemTimeObserver *aObserver) -{ - AssertMainThread(); - sSystemTimeObserver.AddObserver(aObserver); -} - -void -UnregisterSystemTimeChangeObserver(SystemTimeObserver *aObserver) -{ - AssertMainThread(); - sSystemTimeObserver.RemoveObserver(aObserver); -} - -void -NotifySystemTimeChange(const hal::SystemTimeChange& aReason) -{ - sSystemTimeObserver.Broadcast(aReason); -} - void AdjustSystemClock(int32_t aDeltaMilliseconds) { diff --git a/hal/Hal.h b/hal/Hal.h index c039ae95858c..84d96241a456 100644 --- a/hal/Hal.h +++ b/hal/Hal.h @@ -50,8 +50,6 @@ class WindowIdentifier; extern PRLogModuleInfo *sHalLog; #define HAL_LOG(msg) PR_LOG(mozilla::hal::sHalLog, PR_LOG_DEBUG, msg) -typedef Observer<SystemTimeChange> SystemTimeObserver; - } // namespace hal namespace MOZ_HAL_NAMESPACE { @@ -251,24 +249,6 @@ void AdjustSystemClock(int32_t aDeltaMilliseconds); */ void SetTimezone(const nsCString& aTimezoneSpec); -/** - * Register observer for system time changed notification. - * @param aObserver The observer that should be added. - */ -void RegisterSystemTimeChangeObserver(hal::SystemTimeObserver *aObserver); - -/** - * Unregister the observer for system time changed. - * @param aObserver The observer that should be removed. - */ -void UnregisterSystemTimeChangeObserver(hal::SystemTimeObserver *aObserver); - -/** - * Notify of a change in the system cloeck or time zone. - * @param aReason - */ -void NotifySystemTimeChange(const hal::SystemTimeChange& aReason); - /** * Reboot the device. */ diff --git a/hal/HalTypes.h b/hal/HalTypes.h index 189f6e37b527..1833297655a3 100644 --- a/hal/HalTypes.h +++ b/hal/HalTypes.h @@ -71,13 +71,6 @@ enum WakeLockControl { WAKE_LOCK_ADD_ONE = 1, }; -enum SystemTimeChange { - SYS_TIME_CHANGE_UNKNOWN = -1, - SYS_TIME_CHANGE_CLOCK, - SYS_TIME_CHANGE_TZ, - SYS_TIME_CHANGE_GUARD -}; - } // namespace hal } // namespace mozilla @@ -150,16 +143,7 @@ struct ParamTraits<mozilla::hal::ProcessPriority>: mozilla::hal::NUM_PROCESS_PRIORITY> { }; -/** - * SystemTimeChange serializer. - */ -template <> -struct ParamTraits<mozilla::hal::SystemTimeChange> - : public EnumSerializer<mozilla::hal::SystemTimeChange, - mozilla::hal::SYS_TIME_CHANGE_UNKNOWN, - mozilla::hal::SYS_TIME_CHANGE_GUARD> -{}; - + } // namespace IPC #endif // mozilla_hal_Types_h diff --git a/hal/gonk/GonkHal.cpp b/hal/gonk/GonkHal.cpp index abecb162a73a..9ac8fc97bf4d 100644 --- a/hal/gonk/GonkHal.cpp +++ b/hal/gonk/GonkHal.cpp @@ -581,10 +581,6 @@ sys_clock_settime(clockid_t clk_id, const struct timespec *tp) void AdjustSystemClock(int32_t aDeltaMilliseconds) { - if (aDeltaMilliseconds == 0) { - return; - } - struct timespec now; // Preventing context switch before setting system clock @@ -604,34 +600,16 @@ AdjustSystemClock(int32_t aDeltaMilliseconds) now.tv_sec -= 1; } // we need to have root privilege. - if (sys_clock_settime(CLOCK_REALTIME, &now) != 0) { - NS_ERROR("sys_clock_settime failed"); - return; - } - - hal::NotifySystemTimeChange(hal::SYS_TIME_CHANGE_CLOCK); -} - -bool -IsSameTimeZone(const nsCString& aTimezoneSpec) -{ - char timezone[32]; - property_get("persist.sys.timezone", timezone, ""); - return aTimezoneSpec.EqualsASCII(timezone); + sys_clock_settime(CLOCK_REALTIME, &now); } void SetTimezone(const nsCString& aTimezoneSpec) { - if (IsSameTimeZone(aTimezoneSpec)) { - return; - } - property_set("persist.sys.timezone", aTimezoneSpec.get()); // this function is automatically called by the other time conversion // functions that depend on the timezone. To be safe, we call it manually. tzset(); - hal::NotifySystemTimeChange(hal::SYS_TIME_CHANGE_TZ); } // Nothing to do here. Gonk widgetry always listens for screen diff --git a/hal/sandbox/PHal.ipdl b/hal/sandbox/PHal.ipdl index 04cf048b75a8..0e35bf2efaad 100644 --- a/hal/sandbox/PHal.ipdl +++ b/hal/sandbox/PHal.ipdl @@ -24,7 +24,6 @@ using mozilla::hal::SwitchDevice; using mozilla::hal::ProcessPriority; using nsIntRect; using PRTime; -using mozilla::hal::SystemTimeChange; namespace mozilla { @@ -87,7 +86,6 @@ child: NotifyWakeLockChange(WakeLockInformation aWakeLockInfo); NotifyScreenConfigurationChange(ScreenConfiguration aScreenOrientation); NotifySwitchChange(SwitchEvent aEvent); - NotifySystemTimeChange(SystemTimeChange aReason); parent: Vibrate(uint32_t[] pattern, uint64_t[] id, PBrowser browser); diff --git a/hal/sandbox/SandboxHal.cpp b/hal/sandbox/SandboxHal.cpp index 6a3aec8b183a..ed6bdfb63955 100644 --- a/hal/sandbox/SandboxHal.cpp +++ b/hal/sandbox/SandboxHal.cpp @@ -583,11 +583,6 @@ public: hal::SetProcessPriority(aPid, aPriority); return true; } - - void Notify(const SystemTimeChange& aReason) - { - unused << SendNotifySystemTimeChange(aReason); - } }; class HalChild : public PHalChild { @@ -624,12 +619,6 @@ public: hal::NotifySwitchChange(aEvent); return true; } - - virtual bool - RecvNotifySystemTimeChange(const SystemTimeChange& aReason) { - hal::NotifySystemTimeChange(aReason); - return true; - } }; bool diff --git a/layout/build/Makefile.in b/layout/build/Makefile.in index 50d48134dc94..5586bf1fd3cd 100644 --- a/layout/build/Makefile.in +++ b/layout/build/Makefile.in @@ -83,7 +83,6 @@ SHARED_LIBRARY_LIBS = \ $(DEPTH)/dom/indexedDB/$(LIB_PREFIX)dom_indexeddb_s.$(LIB_SUFFIX) \ $(DEPTH)/dom/indexedDB/ipc/$(LIB_PREFIX)dom_indexeddb_ipc_s.$(LIB_SUFFIX) \ $(DEPTH)/dom/browser-element/$(LIB_PREFIX)dom_browserelement_s.$(LIB_SUFFIX) \ - $(DEPTH)/dom/time/$(LIB_PREFIX)dom_time_s.$(LIB_SUFFIX) \ $(DEPTH)/editor/libeditor/text/$(LIB_PREFIX)texteditor_s.$(LIB_SUFFIX) \ $(DEPTH)/editor/libeditor/base/$(LIB_PREFIX)editorbase_s.$(LIB_SUFFIX) \ $(DEPTH)/parser/html/$(LIB_PREFIX)html5p_s.$(LIB_SUFFIX) \ diff --git a/toolkit/toolkit-makefiles.sh b/toolkit/toolkit-makefiles.sh index bfa7e1a80b02..b47ac0f99e8e 100644 --- a/toolkit/toolkit-makefiles.sh +++ b/toolkit/toolkit-makefiles.sh @@ -82,7 +82,6 @@ MAKEFILES_dom=" dom/src/storage/Makefile dom/system/Makefile dom/workers/Makefile - dom/time/Makefile " MAKEFILES_editor=" diff --git a/widget/nsGUIEvent.h b/widget/nsGUIEvent.h index e772b5625037..1b323e3208d7 100644 --- a/widget/nsGUIEvent.h +++ b/widget/nsGUIEvent.h @@ -537,9 +537,6 @@ class nsHashKey; #define NS_POINTERLOCKCHANGE (NS_POINTERLOCK_START) #define NS_POINTERLOCKERROR (NS_POINTERLOCK_START + 1) -//System time is changed -#define NS_MOZ_TIME_CHANGE_EVENT 5400 - /** * Return status for event processors, nsEventStatus, is defined in * nsEvent.h. From 70d87f9165691967021acb0d2de3da5d3c6b5518 Mon Sep 17 00:00:00 2001 From: Eric Faust <efaust@mozilla.com> Date: Tue, 7 Aug 2012 22:26:18 -0700 Subject: [PATCH 130/169] Bug 766448 - Refactor JSPropertySpec and JS_DefineProperties to accept JSJitInfos. (r=Waldo) --- dom/workers/Events.cpp | 88 +++++++++++++++++++------------------ dom/workers/Exceptions.cpp | 15 ++++--- dom/workers/File.cpp | 15 ++++--- dom/workers/ImageData.cpp | 8 ++-- dom/workers/Location.cpp | 30 +++++++------ dom/workers/Navigator.cpp | 18 ++++---- dom/workers/Worker.cpp | 6 +-- dom/workers/WorkerScope.cpp | 20 ++++----- js/src/builtin/RegExp.cpp | 67 ++++++++++++++++++---------- js/src/ctypes/CTypes.cpp | 65 +++++++++++++++------------ js/src/jsapi.cpp | 70 +++++++++++++++++++++++------ js/src/jsapi.h | 35 ++++++++++++--- js/src/jsfriendapi.h | 7 +++ js/src/jsfun.cpp | 6 +-- js/src/jsfun.h | 18 ++++++-- js/src/jsfuninlines.h | 22 ++++++++++ js/src/jsobj.h | 14 +++--- js/src/jsxml.cpp | 24 +++++----- js/src/perf/jsperf.cpp | 4 +- js/src/shell/js.cpp | 22 +++++----- 20 files changed, 350 insertions(+), 204 deletions(-) diff --git a/dom/workers/Events.cpp b/dom/workers/Events.cpp index 2f0be312350b..bfff123634ac 100644 --- a/dom/workers/Events.cpp +++ b/dom/workers/Events.cpp @@ -341,24 +341,25 @@ DECL_EVENT_CLASS(Event::sMainRuntimeClass, "WorkerEvent") #undef DECL_EVENT_CLASS JSPropertySpec Event::sProperties[] = { - { "type", SLOT_type, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub }, - { "target", SLOT_target, PROPERTY_FLAGS, GetProperty, - js_GetterOnlyPropertyStub }, - { "currentTarget", SLOT_currentTarget, PROPERTY_FLAGS, GetProperty, - js_GetterOnlyPropertyStub }, - { "eventPhase", SLOT_eventPhase, PROPERTY_FLAGS, GetProperty, - js_GetterOnlyPropertyStub }, - { "bubbles", SLOT_bubbles, PROPERTY_FLAGS, GetProperty, - js_GetterOnlyPropertyStub }, - { "cancelable", SLOT_cancelable, PROPERTY_FLAGS, GetProperty, - js_GetterOnlyPropertyStub }, - { "timeStamp", SLOT_timeStamp, PROPERTY_FLAGS, GetProperty, - js_GetterOnlyPropertyStub }, - { "defaultPrevented", SLOT_defaultPrevented, PROPERTY_FLAGS, GetProperty, - js_GetterOnlyPropertyStub }, - { "isTrusted", SLOT_isTrusted, PROPERTY_FLAGS, GetProperty, - js_GetterOnlyPropertyStub }, - { 0, 0, 0, NULL, NULL } + { "type", SLOT_type, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { "target", SLOT_target, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { "currentTarget", SLOT_currentTarget, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { "eventPhase", SLOT_eventPhase, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { "bubbles", SLOT_bubbles, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { "cancelable", SLOT_cancelable, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { "timeStamp", SLOT_timeStamp, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { "defaultPrevented", SLOT_defaultPrevented, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { "isTrusted", SLOT_isTrusted, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } }; JSFunctionSpec Event::sFunctions[] = { @@ -370,10 +371,12 @@ JSFunctionSpec Event::sFunctions[] = { }; JSPropertySpec Event::sStaticProperties[] = { - { "CAPTURING_PHASE", CAPTURING_PHASE, CONSTANT_FLAGS, GetConstant, NULL }, - { "AT_TARGET", AT_TARGET, CONSTANT_FLAGS, GetConstant, NULL }, - { "BUBBLING_PHASE", BUBBLING_PHASE, CONSTANT_FLAGS, GetConstant, NULL }, - { 0, 0, 0, NULL, NULL } + { "CAPTURING_PHASE", CAPTURING_PHASE, CONSTANT_FLAGS, + JSOP_WRAPPER(GetConstant), JSOP_NULLWRAPPER }, + { "AT_TARGET", AT_TARGET, CONSTANT_FLAGS, JSOP_WRAPPER(GetConstant), JSOP_NULLWRAPPER }, + { "BUBBLING_PHASE", BUBBLING_PHASE, CONSTANT_FLAGS, + JSOP_WRAPPER(GetConstant), JSOP_NULLWRAPPER }, + { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } }; class MessageEvent : public Event @@ -593,12 +596,13 @@ DECL_MESSAGEEVENT_CLASS(MessageEvent::sMainRuntimeClass, "WorkerMessageEvent") #undef DECL_MESSAGEEVENT_CLASS JSPropertySpec MessageEvent::sProperties[] = { - { "data", SLOT_data, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub }, - { "origin", SLOT_origin, PROPERTY_FLAGS, GetProperty, - js_GetterOnlyPropertyStub }, - { "source", SLOT_source, PROPERTY_FLAGS, GetProperty, - js_GetterOnlyPropertyStub }, - { 0, 0, 0, NULL, NULL } + { "data", SLOT_data, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { "origin", SLOT_origin, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { "source", SLOT_source, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } }; JSFunctionSpec MessageEvent::sFunctions[] = { @@ -778,13 +782,13 @@ DECL_ERROREVENT_CLASS(ErrorEvent::sMainRuntimeClass, "WorkerErrorEvent") #undef DECL_ERROREVENT_CLASS JSPropertySpec ErrorEvent::sProperties[] = { - { "message", SLOT_message, PROPERTY_FLAGS, GetProperty, - js_GetterOnlyPropertyStub }, - { "filename", SLOT_filename, PROPERTY_FLAGS, GetProperty, - js_GetterOnlyPropertyStub }, - { "lineno", SLOT_lineno, PROPERTY_FLAGS, GetProperty, - js_GetterOnlyPropertyStub }, - { 0, 0, 0, NULL, NULL } + { "message", SLOT_message, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { "filename", SLOT_filename, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { "lineno", SLOT_lineno, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } }; JSFunctionSpec ErrorEvent::sFunctions[] = { @@ -952,13 +956,13 @@ JSClass ProgressEvent::sClass = { }; JSPropertySpec ProgressEvent::sProperties[] = { - { "lengthComputable", SLOT_lengthComputable, PROPERTY_FLAGS, GetProperty, - js_GetterOnlyPropertyStub }, - { "loaded", SLOT_loaded, PROPERTY_FLAGS, GetProperty, - js_GetterOnlyPropertyStub }, - { "total", SLOT_total, PROPERTY_FLAGS, GetProperty, - js_GetterOnlyPropertyStub }, - { 0, 0, 0, NULL, NULL } + { "lengthComputable", SLOT_lengthComputable, PROPERTY_FLAGS, + JSOP_WRAPPER(GetProperty), JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { "loaded", SLOT_loaded, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { "total", SLOT_total, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } }; JSFunctionSpec ProgressEvent::sFunctions[] = { diff --git a/dom/workers/Exceptions.cpp b/dom/workers/Exceptions.cpp index cf02c8811c0f..82f270be1eeb 100644 --- a/dom/workers/Exceptions.cpp +++ b/dom/workers/Exceptions.cpp @@ -162,10 +162,13 @@ JSClass DOMException::sClass = { }; JSPropertySpec DOMException::sProperties[] = { - { "code", SLOT_code, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub }, - { "name", SLOT_name, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub }, - { "message", SLOT_message, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub }, - { 0, 0, 0, NULL, NULL } + { "code", SLOT_code, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { "name", SLOT_name, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { "message", SLOT_message, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } }; JSFunctionSpec DOMException::sFunctions[] = { @@ -176,7 +179,7 @@ JSFunctionSpec DOMException::sFunctions[] = { JSPropertySpec DOMException::sStaticProperties[] = { #define EXCEPTION_ENTRY(_name) \ - { #_name, _name, CONSTANT_FLAGS, GetConstant, NULL }, + { #_name, _name, CONSTANT_FLAGS, JSOP_WRAPPER(GetConstant), JSOP_NULLWRAPPER }, EXCEPTION_ENTRY(INDEX_SIZE_ERR) EXCEPTION_ENTRY(DOMSTRING_SIZE_ERR) @@ -206,7 +209,7 @@ JSPropertySpec DOMException::sStaticProperties[] = { #undef EXCEPTION_ENTRY - { 0, 0, 0, NULL, NULL } + { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } }; // static diff --git a/dom/workers/File.cpp b/dom/workers/File.cpp index 86bf1224636e..b7ae3d4521d7 100644 --- a/dom/workers/File.cpp +++ b/dom/workers/File.cpp @@ -210,9 +210,9 @@ JSClass Blob::sClass = { }; JSPropertySpec Blob::sProperties[] = { - { "size", 0, PROPERTY_FLAGS, GetSize, js_GetterOnlyPropertyStub }, - { "type", 0, PROPERTY_FLAGS, GetType, js_GetterOnlyPropertyStub }, - { 0, 0, 0, NULL, NULL } + { "size", 0, PROPERTY_FLAGS, JSOP_WRAPPER(GetSize), JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { "type", 0, PROPERTY_FLAGS, JSOP_WRAPPER(GetType), JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } }; JSFunctionSpec Blob::sFunctions[] = { @@ -360,10 +360,11 @@ JSClass File::sClass = { }; JSPropertySpec File::sProperties[] = { - { "name", 0, PROPERTY_FLAGS, GetName, js_GetterOnlyPropertyStub }, - { "mozFullPath", 0, PROPERTY_FLAGS, GetMozFullPath, - js_GetterOnlyPropertyStub }, - { 0, 0, 0, NULL, NULL } + { "name", 0, PROPERTY_FLAGS, JSOP_WRAPPER(GetName), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { "mozFullPath", 0, PROPERTY_FLAGS, JSOP_WRAPPER(GetMozFullPath), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } }; nsIDOMBlob* diff --git a/dom/workers/ImageData.cpp b/dom/workers/ImageData.cpp index fa2313bfe23b..0195e0bbd4f5 100644 --- a/dom/workers/ImageData.cpp +++ b/dom/workers/ImageData.cpp @@ -148,10 +148,10 @@ JSPropertySpec ImageData::sProperties[] = { // something about it in the mean time. So we use NULL, which defaults to the // class setter (JS_StrictPropertyStub), which is always a silent no-op, // regardless of strict mode. Not ideal, but good enough for now. - { "width", SLOT_width, PROPERTY_FLAGS, GetProperty, NULL }, - { "height", SLOT_height, PROPERTY_FLAGS, GetProperty, NULL }, - { "data", SLOT_data, PROPERTY_FLAGS, GetProperty, NULL }, - { 0, 0, 0, NULL, NULL } + { "width", SLOT_width, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), JSOP_NULLWRAPPER }, + { "height", SLOT_height, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), JSOP_NULLWRAPPER }, + { "data", SLOT_data, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), JSOP_NULLWRAPPER }, + { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } }; } // anonymous namespace diff --git a/dom/workers/Location.cpp b/dom/workers/Location.cpp index 2ca166049041..21bfd098da76 100644 --- a/dom/workers/Location.cpp +++ b/dom/workers/Location.cpp @@ -154,19 +154,23 @@ JSClass Location::sClass = { }; JSPropertySpec Location::sProperties[] = { - { "href", SLOT_href, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub }, - { "protocol", SLOT_protocol, PROPERTY_FLAGS, GetProperty, - js_GetterOnlyPropertyStub }, - { "host", SLOT_host, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub }, - { "hostname", SLOT_hostname, PROPERTY_FLAGS, GetProperty, - js_GetterOnlyPropertyStub }, - { "port", SLOT_port, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub }, - { "pathname", SLOT_pathname, PROPERTY_FLAGS, GetProperty, - js_GetterOnlyPropertyStub }, - { "search", SLOT_search, PROPERTY_FLAGS, GetProperty, - js_GetterOnlyPropertyStub }, - { "hash", SLOT_hash, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub }, - { 0, 0, 0, NULL, NULL } + { "href", SLOT_href, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { "protocol", SLOT_protocol, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { "host", SLOT_host, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { "hostname", SLOT_hostname, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { "port", SLOT_port, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { "pathname", SLOT_pathname, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { "search", SLOT_search, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { "hash", SLOT_hash, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } }; JSFunctionSpec Location::sFunctions[] = { diff --git a/dom/workers/Navigator.cpp b/dom/workers/Navigator.cpp index e95b26284686..3e898b84e811 100644 --- a/dom/workers/Navigator.cpp +++ b/dom/workers/Navigator.cpp @@ -143,15 +143,15 @@ JSClass Navigator::sClass = { }; JSPropertySpec Navigator::sProperties[] = { - { "appName", SLOT_appName, PROPERTY_FLAGS, GetProperty, - js_GetterOnlyPropertyStub }, - { "appVersion", SLOT_appVersion, PROPERTY_FLAGS, GetProperty, - js_GetterOnlyPropertyStub }, - { "platform", SLOT_platform, PROPERTY_FLAGS, GetProperty, - js_GetterOnlyPropertyStub }, - { "userAgent", SLOT_userAgent, PROPERTY_FLAGS, GetProperty, - js_GetterOnlyPropertyStub }, - { 0, 0, 0, NULL, NULL } + { "appName", SLOT_appName, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { "appVersion", SLOT_appVersion, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { "platform", SLOT_platform, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { "userAgent", SLOT_userAgent, PROPERTY_FLAGS, JSOP_WRAPPER(GetProperty), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } }; } // anonymous namespace diff --git a/dom/workers/Worker.cpp b/dom/workers/Worker.cpp index 82dc2104cb5a..d07db062c7ba 100644 --- a/dom/workers/Worker.cpp +++ b/dom/workers/Worker.cpp @@ -292,10 +292,10 @@ DOMJSClass Worker::sClass = { JSPropertySpec Worker::sProperties[] = { { sEventStrings[STRING_onerror], STRING_onerror, PROPERTY_FLAGS, - GetEventListener, SetEventListener }, + JSOP_WRAPPER(GetEventListener), JSOP_WRAPPER(SetEventListener) }, { sEventStrings[STRING_onmessage], STRING_onmessage, PROPERTY_FLAGS, - GetEventListener, SetEventListener }, - { 0, 0, 0, NULL, NULL } + JSOP_WRAPPER(GetEventListener), JSOP_WRAPPER(SetEventListener) }, + { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } }; JSFunctionSpec Worker::sFunctions[] = { diff --git a/dom/workers/WorkerScope.cpp b/dom/workers/WorkerScope.cpp index 57dd3445819c..68496d069654 100644 --- a/dom/workers/WorkerScope.cpp +++ b/dom/workers/WorkerScope.cpp @@ -612,16 +612,16 @@ JSClass WorkerGlobalScope::sClass = { }; JSPropertySpec WorkerGlobalScope::sProperties[] = { - { "location", SLOT_location, PROPERTY_FLAGS, GetLocation, - js_GetterOnlyPropertyStub }, + { "location", SLOT_location, PROPERTY_FLAGS, JSOP_WRAPPER(GetLocation), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, { sEventStrings[STRING_onerror], STRING_onerror, PROPERTY_FLAGS, - GetOnErrorListener, SetOnErrorListener }, + JSOP_WRAPPER(GetOnErrorListener), JSOP_WRAPPER(SetOnErrorListener) }, { sEventStrings[STRING_onclose], STRING_onclose, PROPERTY_FLAGS, - GetEventListener, SetEventListener }, - { "navigator", SLOT_navigator, PROPERTY_FLAGS, GetNavigator, - js_GetterOnlyPropertyStub }, - { "self", 0, PROPERTY_FLAGS, GetSelf, js_GetterOnlyPropertyStub }, - { 0, 0, 0, NULL, NULL } + JSOP_WRAPPER(GetEventListener), JSOP_WRAPPER(SetEventListener) }, + { "navigator", SLOT_navigator, PROPERTY_FLAGS, JSOP_WRAPPER(GetNavigator), + JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { "self", 0, PROPERTY_FLAGS, JSOP_WRAPPER(GetSelf), JSOP_WRAPPER(js_GetterOnlyPropertyStub) }, + { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } }; JSFunctionSpec WorkerGlobalScope::sFunctions[] = { @@ -864,8 +864,8 @@ DOMJSClass DedicatedWorkerGlobalScope::sClass = { JSPropertySpec DedicatedWorkerGlobalScope::sProperties[] = { { sEventStrings[STRING_onmessage], STRING_onmessage, PROPERTY_FLAGS, - GetEventListener, SetEventListener }, - { 0, 0, 0, NULL, NULL } + JSOP_WRAPPER(GetEventListener), JSOP_WRAPPER(SetEventListener) }, + { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } }; JSFunctionSpec DedicatedWorkerGlobalScope::sFunctions[] = { diff --git a/js/src/builtin/RegExp.cpp b/js/src/builtin/RegExp.cpp index ccbb20df82d3..3e12cba57494 100644 --- a/js/src/builtin/RegExp.cpp +++ b/js/src/builtin/RegExp.cpp @@ -436,30 +436,49 @@ const uint8_t HIDDEN_PROP_ATTRS = JSPROP_PERMANENT | JSPROP_SHARED; const uint8_t RO_HIDDEN_PROP_ATTRS = HIDDEN_PROP_ATTRS | JSPROP_READONLY; static JSPropertySpec regexp_static_props[] = { - {"input", 0, REGEXP_STATIC_PROP_ATTRS, static_input_getter, static_input_setter}, - {"multiline", 0, REGEXP_STATIC_PROP_ATTRS, static_multiline_getter, - static_multiline_setter}, - {"lastMatch", 0, RO_REGEXP_STATIC_PROP_ATTRS, static_lastMatch_getter, NULL}, - {"lastParen", 0, RO_REGEXP_STATIC_PROP_ATTRS, static_lastParen_getter, NULL}, - {"leftContext", 0, RO_REGEXP_STATIC_PROP_ATTRS, static_leftContext_getter, NULL}, - {"rightContext", 0, RO_REGEXP_STATIC_PROP_ATTRS, static_rightContext_getter, NULL}, - {"$1", 0, RO_REGEXP_STATIC_PROP_ATTRS, static_paren1_getter, NULL}, - {"$2", 0, RO_REGEXP_STATIC_PROP_ATTRS, static_paren2_getter, NULL}, - {"$3", 0, RO_REGEXP_STATIC_PROP_ATTRS, static_paren3_getter, NULL}, - {"$4", 0, RO_REGEXP_STATIC_PROP_ATTRS, static_paren4_getter, NULL}, - {"$5", 0, RO_REGEXP_STATIC_PROP_ATTRS, static_paren5_getter, NULL}, - {"$6", 0, RO_REGEXP_STATIC_PROP_ATTRS, static_paren6_getter, NULL}, - {"$7", 0, RO_REGEXP_STATIC_PROP_ATTRS, static_paren7_getter, NULL}, - {"$8", 0, RO_REGEXP_STATIC_PROP_ATTRS, static_paren8_getter, NULL}, - {"$9", 0, RO_REGEXP_STATIC_PROP_ATTRS, static_paren9_getter, NULL}, - - {"$_", 0, HIDDEN_PROP_ATTRS, static_input_getter, static_input_setter}, - {"$*", 0, HIDDEN_PROP_ATTRS, static_multiline_getter, static_multiline_setter}, - {"$&", 0, RO_HIDDEN_PROP_ATTRS, static_lastMatch_getter, NULL}, - {"$+", 0, RO_HIDDEN_PROP_ATTRS, static_lastParen_getter, NULL}, - {"$`", 0, RO_HIDDEN_PROP_ATTRS, static_leftContext_getter, NULL}, - {"$'", 0, RO_HIDDEN_PROP_ATTRS, static_rightContext_getter, NULL}, - {0,0,0,0,0} + {"input", 0, REGEXP_STATIC_PROP_ATTRS, JSOP_WRAPPER(static_input_getter), + JSOP_WRAPPER(static_input_setter)}, + {"multiline", 0, REGEXP_STATIC_PROP_ATTRS, JSOP_WRAPPER(static_multiline_getter), + JSOP_WRAPPER(static_multiline_setter)}, + {"lastMatch", 0, RO_REGEXP_STATIC_PROP_ATTRS, JSOP_WRAPPER(static_lastMatch_getter), + JSOP_NULLWRAPPER}, + {"lastParen", 0, RO_REGEXP_STATIC_PROP_ATTRS, JSOP_WRAPPER(static_lastParen_getter), + JSOP_NULLWRAPPER}, + {"leftContext", 0, RO_REGEXP_STATIC_PROP_ATTRS, JSOP_WRAPPER(static_leftContext_getter), + JSOP_NULLWRAPPER}, + {"rightContext", 0, RO_REGEXP_STATIC_PROP_ATTRS, JSOP_WRAPPER(static_rightContext_getter), + JSOP_NULLWRAPPER}, + {"$1", 0, RO_REGEXP_STATIC_PROP_ATTRS, JSOP_WRAPPER(static_paren1_getter), + JSOP_NULLWRAPPER}, + {"$2", 0, RO_REGEXP_STATIC_PROP_ATTRS, JSOP_WRAPPER(static_paren2_getter), + JSOP_NULLWRAPPER}, + {"$3", 0, RO_REGEXP_STATIC_PROP_ATTRS, JSOP_WRAPPER(static_paren3_getter), + JSOP_NULLWRAPPER}, + {"$4", 0, RO_REGEXP_STATIC_PROP_ATTRS, JSOP_WRAPPER(static_paren4_getter), + JSOP_NULLWRAPPER}, + {"$5", 0, RO_REGEXP_STATIC_PROP_ATTRS, JSOP_WRAPPER(static_paren5_getter), + JSOP_NULLWRAPPER}, + {"$6", 0, RO_REGEXP_STATIC_PROP_ATTRS, JSOP_WRAPPER(static_paren6_getter), + JSOP_NULLWRAPPER}, + {"$7", 0, RO_REGEXP_STATIC_PROP_ATTRS, JSOP_WRAPPER(static_paren7_getter), + JSOP_NULLWRAPPER}, + {"$8", 0, RO_REGEXP_STATIC_PROP_ATTRS, JSOP_WRAPPER(static_paren8_getter), + JSOP_NULLWRAPPER}, + {"$9", 0, RO_REGEXP_STATIC_PROP_ATTRS, JSOP_WRAPPER(static_paren9_getter), + JSOP_NULLWRAPPER}, + {"$_", 0, HIDDEN_PROP_ATTRS, JSOP_WRAPPER(static_input_getter), + JSOP_WRAPPER(static_input_setter)}, + {"$*", 0, HIDDEN_PROP_ATTRS, JSOP_WRAPPER(static_multiline_getter), + JSOP_WRAPPER(static_multiline_setter)}, + {"$&", 0, RO_HIDDEN_PROP_ATTRS, JSOP_WRAPPER(static_lastMatch_getter), + JSOP_NULLWRAPPER}, + {"$+", 0, RO_HIDDEN_PROP_ATTRS, JSOP_WRAPPER(static_lastParen_getter), + JSOP_NULLWRAPPER}, + {"$`", 0, RO_HIDDEN_PROP_ATTRS, JSOP_WRAPPER(static_leftContext_getter), + JSOP_NULLWRAPPER}, + {"$'", 0, RO_HIDDEN_PROP_ATTRS, JSOP_WRAPPER(static_rightContext_getter), + JSOP_NULLWRAPPER}, + {0,0,0,JSOP_NULLWRAPPER,JSOP_NULLWRAPPER} }; JSObject * diff --git a/js/src/ctypes/CTypes.cpp b/js/src/ctypes/CTypes.cpp index 7ca152892f96..683a1871cada 100644 --- a/js/src/ctypes/CTypes.cpp +++ b/js/src/ctypes/CTypes.cpp @@ -435,11 +435,11 @@ static JSClass sCDataFinalizerClass = { (JSPROP_READONLY | JSPROP_PERMANENT) static JSPropertySpec sCTypeProps[] = { - { "name", 0, CTYPESPROP_FLAGS, CType::NameGetter, NULL }, - { "size", 0, CTYPESPROP_FLAGS, CType::SizeGetter, NULL }, - { "ptr", 0, CTYPESPROP_FLAGS, CType::PtrGetter, NULL }, - { "prototype", 0, CTYPESPROP_FLAGS, CType::PrototypeGetter, NULL }, - { 0, 0, 0, NULL, NULL } + { "name", 0, CTYPESPROP_FLAGS, JSOP_WRAPPER(CType::NameGetter), JSOP_NULLWRAPPER }, + { "size", 0, CTYPESPROP_FLAGS, JSOP_WRAPPER(CType::SizeGetter), JSOP_NULLWRAPPER }, + { "ptr", 0, CTYPESPROP_FLAGS, JSOP_WRAPPER(CType::PtrGetter), JSOP_NULLWRAPPER }, + { "prototype", 0, CTYPESPROP_FLAGS, JSOP_WRAPPER(CType::PrototypeGetter), JSOP_NULLWRAPPER }, + { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } }; static JSFunctionSpec sCTypeFunctions[] = { @@ -457,8 +457,8 @@ static JSFunctionSpec sCABIFunctions[] = { static JSPropertySpec sCDataProps[] = { { "value", 0, JSPROP_SHARED | JSPROP_PERMANENT, - CData::ValueGetter, CData::ValueSetter }, - { 0, 0, 0, NULL, NULL } + JSOP_WRAPPER(CData::ValueGetter), JSOP_WRAPPER(CData::ValueSetter) }, + { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } }; static JSFunctionSpec sCDataFunctions[] = { @@ -470,7 +470,7 @@ static JSFunctionSpec sCDataFunctions[] = { }; static JSPropertySpec sCDataFinalizerProps[] = { - { 0, 0, 0, NULL, NULL } + { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } }; static JSFunctionSpec sCDataFinalizerFunctions[] = { @@ -486,8 +486,9 @@ static JSFunctionSpec sPointerFunction = JS_FN("PointerType", PointerType::Create, 1, CTYPESCTOR_FLAGS); static JSPropertySpec sPointerProps[] = { - { "targetType", 0, CTYPESPROP_FLAGS, PointerType::TargetTypeGetter, NULL }, - { 0, 0, 0, NULL, NULL } + { "targetType", 0, CTYPESPROP_FLAGS, + JSOP_WRAPPER(PointerType::TargetTypeGetter), JSOP_NULLWRAPPER }, + { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } }; static JSFunctionSpec sPointerInstanceFunctions[] = { @@ -496,20 +497,23 @@ static JSFunctionSpec sPointerInstanceFunctions[] = { JS_FN("decrement", PointerType::Decrement, 0, CTYPESFN_FLAGS), JS_FS_END }; - + static JSPropertySpec sPointerInstanceProps[] = { { "contents", 0, JSPROP_SHARED | JSPROP_PERMANENT, - PointerType::ContentsGetter, PointerType::ContentsSetter }, - { 0, 0, 0, NULL, NULL } + JSOP_WRAPPER(PointerType::ContentsGetter), + JSOP_WRAPPER(PointerType::ContentsSetter) }, + { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } }; static JSFunctionSpec sArrayFunction = JS_FN("ArrayType", ArrayType::Create, 1, CTYPESCTOR_FLAGS); static JSPropertySpec sArrayProps[] = { - { "elementType", 0, CTYPESPROP_FLAGS, ArrayType::ElementTypeGetter, NULL }, - { "length", 0, CTYPESPROP_FLAGS, ArrayType::LengthGetter, NULL }, - { 0, 0, 0, NULL, NULL } + { "elementType", 0, CTYPESPROP_FLAGS, + JSOP_WRAPPER(ArrayType::ElementTypeGetter), JSOP_NULLWRAPPER }, + { "length", 0, CTYPESPROP_FLAGS, + JSOP_WRAPPER(ArrayType::LengthGetter), JSOP_NULLWRAPPER }, + { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } }; static JSFunctionSpec sArrayInstanceFunctions[] = { @@ -519,16 +523,17 @@ static JSFunctionSpec sArrayInstanceFunctions[] = { static JSPropertySpec sArrayInstanceProps[] = { { "length", 0, JSPROP_SHARED | JSPROP_READONLY | JSPROP_PERMANENT, - ArrayType::LengthGetter, NULL }, - { 0, 0, 0, NULL, NULL } + JSOP_WRAPPER(ArrayType::LengthGetter), JSOP_NULLWRAPPER }, + { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } }; static JSFunctionSpec sStructFunction = JS_FN("StructType", StructType::Create, 2, CTYPESCTOR_FLAGS); static JSPropertySpec sStructProps[] = { - { "fields", 0, CTYPESPROP_FLAGS, StructType::FieldsArrayGetter, NULL }, - { 0, 0, 0, NULL, NULL } + { "fields", 0, CTYPESPROP_FLAGS, + JSOP_WRAPPER(StructType::FieldsArrayGetter), JSOP_NULLWRAPPER }, + { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } }; static JSFunctionSpec sStructFunctions[] = { @@ -545,11 +550,15 @@ static JSFunctionSpec sFunctionFunction = JS_FN("FunctionType", FunctionType::Create, 2, CTYPESCTOR_FLAGS); static JSPropertySpec sFunctionProps[] = { - { "argTypes", 0, CTYPESPROP_FLAGS, FunctionType::ArgTypesGetter, NULL }, - { "returnType", 0, CTYPESPROP_FLAGS, FunctionType::ReturnTypeGetter, NULL }, - { "abi", 0, CTYPESPROP_FLAGS, FunctionType::ABIGetter, NULL }, - { "isVariadic", 0, CTYPESPROP_FLAGS, FunctionType::IsVariadicGetter, NULL }, - { 0, 0, 0, NULL, NULL } + { "argTypes", 0, CTYPESPROP_FLAGS, + JSOP_WRAPPER(FunctionType::ArgTypesGetter), JSOP_NULLWRAPPER }, + { "returnType", 0, CTYPESPROP_FLAGS, + JSOP_WRAPPER(FunctionType::ReturnTypeGetter), JSOP_NULLWRAPPER }, + { "abi", 0, CTYPESPROP_FLAGS, + JSOP_WRAPPER(FunctionType::ABIGetter), JSOP_NULLWRAPPER }, + { "isVariadic", 0, CTYPESPROP_FLAGS, + JSOP_WRAPPER(FunctionType::IsVariadicGetter), JSOP_NULLWRAPPER }, + { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } }; static JSFunctionSpec sFunctionInstanceFunctions[] = { @@ -616,12 +625,12 @@ static JSFunctionSpec sUInt64Functions[] = { static JSPropertySpec sModuleProps[] = { { "errno", 0, JSPROP_SHARED | JSPROP_PERMANENT, - CData::ErrnoGetter, NULL }, + JSOP_WRAPPER(CData::ErrnoGetter), JSOP_NULLWRAPPER }, #if defined(XP_WIN) { "winLastError", 0, JSPROP_SHARED | JSPROP_PERMANENT, - CData::LastErrorGetter, NULL }, + JSOP_WRAPPER(CData::LastErrorGetter), JSOP_NULLWRAPPER }, #endif // defined(XP_WIN) - { 0, 0, 0, NULL, NULL } + { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } }; static JSFunctionSpec sModuleFunctions[] = { diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 60834c70d808..9ad2fcc55fc0 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -3781,11 +3781,34 @@ JS_AlreadyHasOwnUCProperty(JSContext *cx, JSObject *objArg, const jschar *name, return atom && JS_AlreadyHasOwnPropertyById(cx, obj, AtomToId(atom), foundp); } +/* Wrapper functions to create wrappers with no corresponding JSJitInfo from API + * function arguments. + */ +static JSPropertyOpWrapper +GetterWrapper(JSPropertyOp getter) +{ + JSPropertyOpWrapper ret; + ret.op = getter; + ret.info = NULL; + return ret; +} + +static JSStrictPropertyOpWrapper +SetterWrapper(JSStrictPropertyOp setter) +{ + JSStrictPropertyOpWrapper ret; + ret.op = setter; + ret.info = NULL; + return ret; +} + static JSBool DefinePropertyById(JSContext *cx, HandleObject obj, HandleId id, HandleValue value, - PropertyOp getter, StrictPropertyOp setter, unsigned attrs, - unsigned flags, int tinyid) + const JSPropertyOpWrapper &get, const JSStrictPropertyOpWrapper &set, + unsigned attrs, unsigned flags, int tinyid) { + PropertyOp getter = get.op; + StrictPropertyOp setter = set.op; /* * JSPROP_READONLY has no meaning when accessors are involved. Ideally we'd * throw if this happens, but we've accepted it for long enough that it's @@ -3806,9 +3829,13 @@ DefinePropertyById(JSContext *cx, HandleObject obj, HandleId id, HandleValue val attrs &= ~JSPROP_NATIVE_ACCESSORS; if (getter) { RootedObject global(cx, (JSObject*) &obj->global()); - JSObject *getobj = JS_NewFunction(cx, (Native) getter, 0, 0, global, NULL); + JSFunction *getobj = JS_NewFunction(cx, (Native) getter, 0, 0, global, NULL); if (!getobj) return false; + + if (get.info) + getobj->setJitInfo(get.info); + getter = JS_DATA_TO_FUNC_PTR(PropertyOp, getobj); attrs |= JSPROP_GETTER; } @@ -3816,9 +3843,13 @@ DefinePropertyById(JSContext *cx, HandleObject obj, HandleId id, HandleValue val // Root just the getter, since the setter is not yet a JSObject. AutoRooterGetterSetter getRoot(cx, JSPROP_GETTER, &getter, NULL); RootedObject global(cx, (JSObject*) &obj->global()); - JSObject *setobj = JS_NewFunction(cx, (Native) setter, 1, 0, global, NULL); + JSFunction *setobj = JS_NewFunction(cx, (Native) setter, 1, 0, global, NULL); if (!setobj) return false; + + if (set.info) + setobj->setJitInfo(set.info); + setter = JS_DATA_TO_FUNC_PTR(StrictPropertyOp, setobj); attrs |= JSPROP_SETTER; } @@ -3850,7 +3881,8 @@ JS_DefinePropertyById(JSContext *cx, JSObject *objArg, jsid idArg, jsval value_, RootedObject obj(cx, objArg); RootedId id(cx, idArg); RootedValue value(cx, value_); - return DefinePropertyById(cx, obj, id, value, getter, setter, attrs, 0, 0); + return DefinePropertyById(cx, obj, id, value, GetterWrapper(getter), + SetterWrapper(setter), attrs, 0, 0); } JS_PUBLIC_API(JSBool) @@ -3865,16 +3897,18 @@ JS_DefineElement(JSContext *cx, JSObject *objArg, uint32_t index, jsval valueArg RootedId id(cx); if (!IndexToId(cx, index, id.address())) return false; - return DefinePropertyById(cx, obj, id, value, getter, setter, attrs, 0, 0); + return DefinePropertyById(cx, obj, id, value, GetterWrapper(getter), + SetterWrapper(setter), attrs, 0, 0); } static JSBool DefineProperty(JSContext *cx, JSHandleObject obj, const char *name, const Value &value_, - PropertyOp getter, StrictPropertyOp setter, unsigned attrs, - unsigned flags, int tinyid) + const JSPropertyOpWrapper &getter, const JSStrictPropertyOpWrapper &setter, + unsigned attrs, unsigned flags, int tinyid) { RootedValue value(cx, value_); - AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter); + AutoRooterGetterSetter gsRoot(cx, attrs, const_cast<JSPropertyOp *>(&getter.op), + const_cast<JSStrictPropertyOp *>(&setter.op)); RootedId id(cx); if (attrs & JSPROP_INDEX) { @@ -3895,7 +3929,8 @@ JS_DefineProperty(JSContext *cx, JSObject *objArg, const char *name, jsval value PropertyOp getter, JSStrictPropertyOp setter, unsigned attrs) { RootedObject obj(cx, objArg); - return DefineProperty(cx, obj, name, value, getter, setter, attrs, 0, 0); + return DefineProperty(cx, obj, name, value, GetterWrapper(getter), + SetterWrapper(setter), attrs, 0, 0); } JS_PUBLIC_API(JSBool) @@ -3903,7 +3938,8 @@ JS_DefinePropertyWithTinyId(JSContext *cx, JSObject *objArg, const char *name, i jsval value, PropertyOp getter, JSStrictPropertyOp setter, unsigned attrs) { RootedObject obj(cx, objArg); - return DefineProperty(cx, obj, name, value, getter, setter, attrs, Shape::HAS_SHORTID, tinyid); + return DefineProperty(cx, obj, name, value, GetterWrapper(getter), + SetterWrapper(setter), attrs, Shape::HAS_SHORTID, tinyid); } static JSBool @@ -3917,7 +3953,8 @@ DefineUCProperty(JSContext *cx, JSHandleObject obj, const jschar *name, size_t n if (!atom) return false; RootedId id(cx, AtomToId(atom)); - return DefinePropertyById(cx, obj, id, value, getter, setter, attrs, flags, tinyid); + return DefinePropertyById(cx, obj, id, value, GetterWrapper(getter), + SetterWrapper(setter), attrs, flags, tinyid); } JS_PUBLIC_API(JSBool) @@ -3968,8 +4005,11 @@ JS_DefineObject(JSContext *cx, JSObject *objArg, const char *name, JSClass *jscl if (!nobj) return NULL; - if (!DefineProperty(cx, obj, name, ObjectValue(*nobj), NULL, NULL, attrs, 0, 0)) + if (!DefineProperty(cx, obj, name, ObjectValue(*nobj), GetterWrapper(NULL), + SetterWrapper(NULL), attrs, 0, 0)) + { return NULL; + } return nobj; } @@ -3983,12 +4023,14 @@ JS_DefineConstDoubles(JSContext *cx, JSObject *objArg, JSConstDoubleSpec *cds) AssertHeapIsIdle(cx); CHECK_REQUEST(cx); + JSPropertyOpWrapper noget = GetterWrapper(NULL); + JSStrictPropertyOpWrapper noset = SetterWrapper(NULL); for (ok = JS_TRUE; cds->name; cds++) { Value value = DoubleValue(cds->dval); attrs = cds->flags; if (!attrs) attrs = JSPROP_READONLY | JSPROP_PERMANENT; - ok = DefineProperty(cx, obj, cds->name, value, NULL, NULL, attrs, 0, 0); + ok = DefineProperty(cx, obj, cds->name, value, noget, noset, attrs, 0, 0); if (!ok) break; } diff --git a/js/src/jsapi.h b/js/src/jsapi.h index cc34734bb36f..f1a904413296 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -4335,17 +4335,42 @@ struct JSConstDoubleSpec { uint8_t spare[3]; }; +typedef struct JSJitInfo JSJitInfo; + +/* + * Wrappers to replace {Strict,}PropertyOp for JSPropertySpecs. This will allow + * us to pass one JSJitInfo per function with the property spec, without + * additional field overhead. + */ +typedef struct JSStrictPropertyOpWrapper { + JSStrictPropertyOp op; + const JSJitInfo *info; +} JSStrictPropertyOpWrapper; + +typedef struct JSPropertyOpWrapper { + JSPropertyOp op; + const JSJitInfo *info; +} JSPropertyOpWrapper; + +/* + * Macro static initializers which correspond to the old |op| and |NULL| + * respectively, and make it easy to pass no JSJitInfo as part of a + * JSPropertySpec. + */ +#define JSOP_WRAPPER(op) {op, NULL} +#define JSOP_NULLWRAPPER JSOP_WRAPPER(NULL) + /* * To define an array element rather than a named property member, cast the * element's index to (const char *) and initialize name with it, and set the * JSPROP_INDEX bit in flags. */ struct JSPropertySpec { - const char *name; - int8_t tinyid; - uint8_t flags; - JSPropertyOp getter; - JSStrictPropertyOp setter; + const char *name; + int8_t tinyid; + uint8_t flags; + JSPropertyOpWrapper getter; + JSStrictPropertyOpWrapper setter; }; struct JSFunctionSpec { diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index eb64565044e6..3936ded5d236 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -1292,4 +1292,11 @@ JS_GetDataViewByteLength(JSObject *obj, JSContext *cx); JS_FRIEND_API(void *) JS_GetDataViewData(JSObject *obj, JSContext *cx); +/* + * This struct contains metadata passed from the DOM to the JS Engine for JIT + * optimizations on DOM property accessors. Eventually, this should be made + * available to general JSAPI users, but we are not currently ready to do so. + */ +struct JSJitInfo; + #endif /* jsfriendapi_h___ */ diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 8c50307b40f9..890a1214a6b5 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -1385,8 +1385,8 @@ js_NewFunction(JSContext *cx, JSObject *funobj, Native native, unsigned nargs, fun->mutableScript().init(NULL); fun->initEnvironment(parent); } else { - fun->u.native = native; - JS_ASSERT(fun->u.native); + JS_ASSERT(native); + fun->initNative(native, NULL); } if (kind == JSFunction::ExtendedFinalizeKind) { fun->flags |= JSFUN_EXTENDED; @@ -1419,7 +1419,7 @@ js_CloneFunctionObject(JSContext *cx, HandleFunction fun, HandleObject parent, clone->initScript(fun->script()); clone->initEnvironment(parent); } else { - clone->u.native = fun->native(); + clone->initNative(fun->native(), fun->jitInfo()); } clone->atom.init(fun->atom); diff --git a/js/src/jsfun.h b/js/src/jsfun.h index 1eadee209f5a..f22be354f2bf 100644 --- a/js/src/jsfun.h +++ b/js/src/jsfun.h @@ -49,7 +49,13 @@ struct JSFunction : public JSObject reflected as f.length/f.arity */ uint16_t flags; /* flags, see JSFUN_* below and in jsapi.h */ union U { - js::Native native; /* native method pointer or null */ + class Native { + friend struct JSFunction; + js::Native native; /* native method pointer or null */ + const JSJitInfo *jitinfo; /* Information about this function to be + used by the JIT; + use the accessor! */ + } n; struct Scripted { JSScript *script_; /* interpreted bytecode descriptor or null; use the accessor! */ @@ -120,16 +126,20 @@ struct JSFunction : public JSObject JSNative native() const { JS_ASSERT(isNative()); - return u.native; + return u.n.native; } JSNative maybeNative() const { return isInterpreted() ? NULL : native(); } + inline void initNative(js::Native native, const JSJitInfo *jitinfo); + inline const JSJitInfo *jitInfo() const; + inline void setJitInfo(const JSJitInfo *data); + static unsigned offsetOfNativeOrScript() { - JS_STATIC_ASSERT(offsetof(U, native) == offsetof(U, i.script_)); - JS_STATIC_ASSERT(offsetof(U, native) == offsetof(U, nativeOrScript)); + JS_STATIC_ASSERT(offsetof(U, n.native) == offsetof(U, i.script_)); + JS_STATIC_ASSERT(offsetof(U, n.native) == offsetof(U, nativeOrScript)); return offsetof(JSFunction, u.nativeOrScript); } diff --git a/js/src/jsfuninlines.h b/js/src/jsfuninlines.h index 1ac2e8102703..766c92bad76f 100644 --- a/js/src/jsfuninlines.h +++ b/js/src/jsfuninlines.h @@ -42,6 +42,28 @@ JSFunction::initEnvironment(JSObject *obj) ((js::HeapPtrObject *)&u.i.env_)->init(obj); } +inline void +JSFunction::initNative(js::Native native, const JSJitInfo *data) +{ + JS_ASSERT(native); + u.n.native = native; + u.n.jitinfo = data; +} + +inline const JSJitInfo * +JSFunction::jitInfo() const +{ + JS_ASSERT(isNative()); + return u.n.jitinfo; +} + +inline void +JSFunction::setJitInfo(const JSJitInfo *data) +{ + JS_ASSERT(isNative()); + u.n.jitinfo = data; +} + inline void JSFunction::initializeExtended() { diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 7b89347ca786..cdb7ad34efd3 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -72,13 +72,13 @@ CastAsObjectJsval(StrictPropertyOp op) * JSNatives. To avoid widespread casting, have JS_PSG and JS_PSGS perform * type-safe casts. */ -#define JS_PSG(name,getter,flags) \ - {name, 0, (flags) | JSPROP_SHARED | JSPROP_NATIVE_ACCESSORS, \ - (JSPropertyOp)getter, NULL} -#define JS_PSGS(name,getter,setter,flags) \ - {name, 0, (flags) | JSPROP_SHARED | JSPROP_NATIVE_ACCESSORS, \ - (JSPropertyOp)getter, (JSStrictPropertyOp)setter} -#define JS_PS_END {0, 0, 0, 0, 0} +#define JS_PSG(name,getter,flags) \ + {name, 0, (flags) | JSPROP_SHARED | JSPROP_NATIVE_ACCESSORS, \ + JSOP_WRAPPER((JSPropertyOp)getter), JSOP_NULLWRAPPER} +#define JS_PSGS(name,getter,setter,flags) \ + {name, 0, (flags) | JSPROP_SHARED | JSPROP_NATIVE_ACCESSORS, \ + JSOP_WRAPPER((JSPropertyOp)getter), JSOP_WRAPPER((JSStrictPropertyOp)setter)} +#define JS_PS_END {0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER} /******************************************************************************/ diff --git a/js/src/jsxml.cpp b/js/src/jsxml.cpp index e6d88d25d42f..1e0e62a9166a 100644 --- a/js/src/jsxml.cpp +++ b/js/src/jsxml.cpp @@ -197,9 +197,9 @@ JS_FRIEND_DATA(Class) js::NamespaceClass = { (JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED) static JSPropertySpec namespace_props[] = { - {js_prefix_str, 0, NAMESPACE_ATTRS, NamePrefix_getter, 0}, - {js_uri_str, 0, NAMESPACE_ATTRS, NameURI_getter, 0}, - {0,0,0,0,0} + {js_prefix_str, 0, NAMESPACE_ATTRS, JSOP_WRAPPER(NamePrefix_getter), JSOP_NULLWRAPPER}, + {js_uri_str, 0, NAMESPACE_ATTRS, JSOP_WRAPPER(NameURI_getter), JSOP_NULLWRAPPER}, + {0,0,0,JSOP_NULLWRAPPER, JSOP_NULLWRAPPER} }; static JSBool @@ -341,9 +341,9 @@ JS_FRIEND_DATA(Class) js::AnyNameClass = { #define QNAME_ATTRS (JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED) static JSPropertySpec qname_props[] = { - {js_uri_str, 0, QNAME_ATTRS, QNameNameURI_getter, 0}, - {js_localName_str, 0, QNAME_ATTRS, QNameLocalName_getter, 0}, - {0,0,0,0,0} + {js_uri_str, 0, QNAME_ATTRS, JSOP_WRAPPER(QNameNameURI_getter), JSOP_NULLWRAPPER}, + {js_localName_str, 0, QNAME_ATTRS, JSOP_WRAPPER(QNameLocalName_getter), JSOP_NULLWRAPPER}, + {0,0,0,JSOP_NULLWRAPPER,JSOP_NULLWRAPPER} }; static JSString * @@ -1114,12 +1114,12 @@ static const char js_prettyIndent_str[] = "prettyIndent"; #define XSF_PRETTY_PRINTING JS_BIT(3) static JSPropertySpec xml_static_props[] = { - {js_ignoreComments_str, 0, JSPROP_PERMANENT, NULL, NULL}, - {js_ignoreProcessingInstructions_str, 0, JSPROP_PERMANENT, NULL, NULL}, - {js_ignoreWhitespace_str, 0, JSPROP_PERMANENT, NULL, NULL}, - {js_prettyPrinting_str, 0, JSPROP_PERMANENT, NULL, NULL}, - {js_prettyIndent_str, 0, JSPROP_PERMANENT, NULL, NULL}, - {0,0,0,0,0} + {js_ignoreComments_str, 0, JSPROP_PERMANENT, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER}, + {js_ignoreProcessingInstructions_str, 0, JSPROP_PERMANENT, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER}, + {js_ignoreWhitespace_str, 0, JSPROP_PERMANENT, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER}, + {js_prettyPrinting_str, 0, JSPROP_PERMANENT, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER}, + {js_prettyIndent_str, 0, JSPROP_PERMANENT, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER}, + {0,0,0,JSOP_NULLWRAPPER, JSOP_NULLWRAPPER} }; /* Macros for special-casing xml:, xmlns= and xmlns:foo= in ParseNodeToQName. */ diff --git a/js/src/perf/jsperf.cpp b/js/src/perf/jsperf.cpp index 52c366461882..b601daebdcd9 100644 --- a/js/src/perf/jsperf.cpp +++ b/js/src/perf/jsperf.cpp @@ -103,7 +103,7 @@ const uint8_t PM_PATTRS = JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED; #define GETTER(name) \ - { #name, 0, PM_PATTRS, pm_get_##name, 0 } + { #name, 0, PM_PATTRS, JSOP_WRAPPER(pm_get_##name), JSOP_NULLWRAPPER } static JSPropertySpec pm_props[] = { GETTER(cpu_cycles), @@ -118,7 +118,7 @@ static JSPropertySpec pm_props[] = { GETTER(context_switches), GETTER(cpu_migrations), GETTER(eventsMeasured), - {0,0,0,0,0} + {0,0,0,JSOP_NULLWRAPPER,JSOP_NULLWRAPPER} }; #undef GETTER diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 307633c49e41..3bf7c03d074f 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -3928,21 +3928,21 @@ static JSBool its_set_customNative(JSContext *cx, unsigned argc, jsval *vp); static JSPropertySpec its_props[] = { - {"color", ITS_COLOR, JSPROP_ENUMERATE, NULL, NULL}, - {"height", ITS_HEIGHT, JSPROP_ENUMERATE, NULL, NULL}, - {"width", ITS_WIDTH, JSPROP_ENUMERATE, NULL, NULL}, - {"funny", ITS_FUNNY, JSPROP_ENUMERATE, NULL, NULL}, - {"array", ITS_ARRAY, JSPROP_ENUMERATE, NULL, NULL}, - {"rdonly", ITS_RDONLY, JSPROP_READONLY, NULL, NULL}, + {"color", ITS_COLOR, JSPROP_ENUMERATE, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER}, + {"height", ITS_HEIGHT, JSPROP_ENUMERATE, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER}, + {"width", ITS_WIDTH, JSPROP_ENUMERATE, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER}, + {"funny", ITS_FUNNY, JSPROP_ENUMERATE, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER}, + {"array", ITS_ARRAY, JSPROP_ENUMERATE, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER}, + {"rdonly", ITS_RDONLY, JSPROP_READONLY, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER}, {"custom", ITS_CUSTOM, JSPROP_ENUMERATE, - its_getter, its_setter}, + JSOP_WRAPPER(its_getter), JSOP_WRAPPER(its_setter)}, {"customRdOnly", ITS_CUSTOMRDONLY, JSPROP_ENUMERATE | JSPROP_READONLY, - its_getter, its_setter}, + JSOP_WRAPPER(its_getter), JSOP_WRAPPER(its_setter)}, {"customNative", ITS_CUSTOMNATIVE, JSPROP_ENUMERATE | JSPROP_NATIVE_ACCESSORS, - (JSPropertyOp)its_get_customNative, - (JSStrictPropertyOp)its_set_customNative }, - {NULL,0,0,NULL,NULL} + JSOP_WRAPPER((JSPropertyOp)its_get_customNative), + JSOP_WRAPPER((JSStrictPropertyOp)its_set_customNative)}, + {NULL,0,0,JSOP_NULLWRAPPER, JSOP_NULLWRAPPER} }; static JSBool its_noisy; /* whether to be noisy when finalizing it */ From fe56a76a4c398c743f76f4c27ca4e656a3552ef8 Mon Sep 17 00:00:00 2001 From: Eric Faust <efaust@mozilla.com> Date: Tue, 7 Aug 2012 22:26:18 -0700 Subject: [PATCH 131/169] Bug 747287 - Part 1: Generate JSJitInfos and specialized accessors for Paris bindings. (r=peterv) --- dom/bindings/BindingUtils.cpp | 4 +- dom/bindings/Codegen.py | 151 +++++++++++++++++++++++++++------- js/src/jsfriendapi.h | 14 +++- 3 files changed, 136 insertions(+), 33 deletions(-) diff --git a/dom/bindings/BindingUtils.cpp b/dom/bindings/BindingUtils.cpp index 0c4a0fd93584..f2dd4a2783f5 100644 --- a/dom/bindings/BindingUtils.cpp +++ b/dom/bindings/BindingUtils.cpp @@ -458,8 +458,8 @@ XrayResolveProperty(JSContext* cx, JSObject* wrapper, jsid id, if (id == attributeIds[i]) { desc->attrs = attributeSpecs[i].flags; desc->obj = wrapper; - desc->setter = attributeSpecs[i].setter; - desc->getter = attributeSpecs[i].getter; + desc->setter = attributeSpecs[i].setter.op; + desc->getter = attributeSpecs[i].getter.op; return true; } } diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index edb95f9a9a12..497d3f6bddb3 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -961,12 +961,14 @@ class AttrDefiner(PropertyDefiner): return flags def getter(attr): - return "get_" + attr.identifier.name + return ("{(JSPropertyOp)get_%(name)s, &%(name)s_getterinfo}" + % {"name" : attr.identifier.name}) def setter(attr): if attr.readonly: - return "NULL" - return "set_" + attr.identifier.name + return "JSOP_NULLWRAPPER" + return ("{(JSStrictPropertyOp)set_%(name)s, &%(name)s_setterinfo}" + % {"name" : attr.identifier.name}) def specData(attr): return (attr.identifier.name, flags(attr), getter(attr), @@ -974,8 +976,8 @@ class AttrDefiner(PropertyDefiner): return self.generatePrefableArray( array, name, - ' { "%s", 0, %s, (JSPropertyOp)%s, (JSStrictPropertyOp)%s }', - ' { 0, 0, 0, 0, 0 }', + ' { "%s", 0, %s, %s, %s}', + ' { 0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER }', 'JSPropertySpec', PropertyDefiner.getControllingPref, specData, doIdArrays) @@ -3180,23 +3182,12 @@ class CGSetterCall(CGGetterSetterCall): nativeMethodName, descriptor, attr, setter=True) def wrap_return_value(self): - if generateNativeAccessors: - return CGGetterSetterCall.wrap_return_value(self) # We have no return value return "\nreturn true;" def getArgc(self): - if generateNativeAccessors: - return CGGetterSetterCall.getArgc(self) return "1" def getArgvDecl(self): - if generateNativeAccessors: - return (CGPerSignatureCall.getArgvDecl(self) + - "jsval undef = JS::UndefinedValue();\n" - "if (argc == 0) {\n" - " argv = &undef;\n" - " argc = 1;\n" - "}") - # We just get our stuff from vp + # We just get our stuff from our last arg no matter what return "" class FakeCastableDescriptor(): @@ -3231,7 +3222,7 @@ class CGAbstractBindingMethod(CGAbstractStaticMethod): def getThis(self): return CGIndenter( - CGGeneric("JSObject* obj = JS_THIS_OBJECT(cx, vp);\n" + CGGeneric("JS::RootedObject obj(cx, JS_THIS_OBJECT(cx, vp));\n" "if (!obj) {\n" " return false;\n" "}\n" @@ -3282,10 +3273,29 @@ class CGNativeGetter(CGAbstractBindingMethod): CGGeneric("%s* self;" % self.descriptor.nativeType)) def generate_code(self): + return CGIndenter(CGGeneric( + "return specialized_get_%s(cx, obj, self, vp);" % + self.attr.identifier.name)) + +class CGSpecializedGetter(CGAbstractStaticMethod): + """ + A class for generating the code for a specialized attribute getter + that the JIT can call with lower overhead. + """ + def __init__(self, descriptor, attr): + self.attr = attr + name = 'specialized_get_' + attr.identifier.name + args = [ Argument('JSContext*', 'cx'), + Argument('JSHandleObject', 'obj'), + Argument('%s*' % descriptor.nativeType, 'self'), + Argument('JS::Value*', 'vp') ] + CGAbstractStaticMethod.__init__(self, descriptor, name, "bool", args) + + def definition_body(self): name = self.attr.identifier.name nativeName = "Get" + MakeNativeName(self.descriptor.binaryNames.get(name, name)) - return CGIndenter(CGGetterCall(self.attr.type, nativeName, self.descriptor, - self.attr)) + return CGIndenter(CGGetterCall(self.attr.type, nativeName, + self.descriptor, self.attr)).define() class CGNativeSetter(CGAbstractBindingMethod): """ @@ -3311,10 +3321,89 @@ class CGNativeSetter(CGAbstractBindingMethod): CGGeneric("%s* self;" % self.descriptor.nativeType)) def generate_code(self): + if generateNativeAccessors: + argv = ("JS::Value* argv = JS_ARGV(cx, vp);\n" + "jsval undef = JS::UndefinedValue();\n" + "if (argc == 0) {\n" + " argv = &undef;\n" + "}\n") + retval = "*vp = JSVAL_VOID;\n" + else: + argv = "JS::Value* argv = vp;\n" + retval = "" + + return CGIndenter(CGGeneric( + argv + + ("if (!specialized_set_%s(cx, obj, self, argv)) {\n" + " return false;\n" + "}\n" % self.attr.identifier.name) + + retval + + "return true;")) + +class CGSpecializedSetter(CGAbstractStaticMethod): + """ + A class for generating the code for a specialized attribute setter + that the JIT can call with lower overhead. + """ + def __init__(self, descriptor, attr): + self.attr = attr + name = 'specialized_set_' + attr.identifier.name + args = [ Argument('JSContext*', 'cx'), + Argument('JSHandleObject', 'obj'), + Argument('%s*' % descriptor.nativeType, 'self') ] + # Our last argument is named differently depending on whether we're + # in the native accessors case or not + if generateNativeAccessors: + args.append(Argument('JS::Value*', 'argv')) + else: + args.append(Argument('JS::Value*', 'vp')) + CGAbstractStaticMethod.__init__(self, descriptor, name, "bool", args) + + def definition_body(self): name = self.attr.identifier.name nativeName = "Set" + MakeNativeName(self.descriptor.binaryNames.get(name, name)) - return CGIndenter(CGSetterCall(self.attr.type, nativeName, self.descriptor, - self.attr)) + return CGIndenter(CGSetterCall(self.attr.type, nativeName, + self.descriptor, self.attr)).define() + +class CGPropertyJITInfo(CGThing): + """ + A class for generating the JITInfo for a property that points to + our specialized getter and setter. + """ + def __init__(self, descriptor, attr): + self.attr = attr + self.descriptor = descriptor + + def declare(self): + return "" + + def defineJitInfo(self, infoName, opName, infallible): + protoID = "prototypes::id::%s" % self.descriptor.interface.identifier.name + depth = "PrototypeTraits<%s>::Depth" % protoID + failstr = "true" if infallible else "false" + return ("\n" + "const JSJitInfo %s = {\n" + " %s,\n" + " %s,\n" + " %s,\n" + " %s, /* isInfallible. False for setters. */\n" + " false /* isConstant. False for setters. */\n" + "};\n" % (infoName, opName, protoID, depth, failstr)) + + def define(self): + getterinfo = ("%s_getterinfo" % self.attr.identifier.name) + getter = ("(JSJitPropertyOp)specialized_get_%s" % + self.attr.identifier.name) + # For now, mark all getters fallible, until argument wrapping has been + # handled. + result = self.defineJitInfo(getterinfo, getter, False) + if not self.attr.readonly: + setterinfo = ("%s_setterinfo" % self.attr.identifier.name) + setter = ("(JSJitPropertyOp)specialized_set_%s" % + self.attr.identifier.name) + # Setters are always fallible, since they have to do a typed unwrap. + result += self.defineJitInfo(setterinfo, setter, False) + return result def getEnumValueName(value): # Some enum values can be empty strings. Others might have weird @@ -4052,14 +4141,16 @@ class CGDescriptor(CGThing): cgThings = [] if descriptor.interface.hasInterfacePrototypeObject(): - cgThings.extend([CGNativeMethod(descriptor, m) for m in - descriptor.interface.members if - m.isMethod() and not m.isStatic()]) - cgThings.extend([CGNativeGetter(descriptor, a) for a in - descriptor.interface.members if a.isAttr()]) - cgThings.extend([CGNativeSetter(descriptor, a) for a in - descriptor.interface.members if - a.isAttr() and not a.readonly]) + for m in descriptor.interface.members: + if m.isMethod() and not m.isStatic(): + cgThings.append(CGNativeMethod(descriptor, m)) + elif m.isAttr(): + cgThings.append(CGSpecializedGetter(descriptor, m)) + cgThings.append(CGNativeGetter(descriptor, m)) + if not m.readonly: + cgThings.append(CGSpecializedSetter(descriptor, m)) + cgThings.append(CGNativeSetter(descriptor, m)) + cgThings.append(CGPropertyJITInfo(descriptor, m)) if descriptor.concrete: if not descriptor.workers and descriptor.wrapperCache: diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index 3936ded5d236..7a8e30ac55c5 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -1292,11 +1292,23 @@ JS_GetDataViewByteLength(JSObject *obj, JSContext *cx); JS_FRIEND_API(void *) JS_GetDataViewData(JSObject *obj, JSContext *cx); +#ifdef __cplusplus /* * This struct contains metadata passed from the DOM to the JS Engine for JIT * optimizations on DOM property accessors. Eventually, this should be made * available to general JSAPI users, but we are not currently ready to do so. */ -struct JSJitInfo; +typedef bool +(* JSJitPropertyOp)(JSContext *cx, JSObject *thisObj, + void *specializedThis, JS::Value *vp); + +struct JSJitInfo { + JSJitPropertyOp op; + uint32_t protoID; + uint32_t depth; + bool isInfallible; /* Is op fallible? Getters only */ + bool isConstant; /* Getting a construction-time constant? */ +}; +#endif #endif /* jsfriendapi_h___ */ From 54f8c4dcea8578b10d1aca4c451a81428d1e5a43 Mon Sep 17 00:00:00 2001 From: Eric Faust <efaust@mozilla.com> Date: Tue, 7 Aug 2012 22:26:18 -0700 Subject: [PATCH 132/169] Bug 747287 - Part 2: Generate infalliblity data for further JIT optimization. (r=peterv) --- dom/bindings/Codegen.py | 81 ++++++++++++++++++++++++++--------------- 1 file changed, 52 insertions(+), 29 deletions(-) diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index 497d3f6bddb3..a4681f24d790 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -2404,6 +2404,8 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode, "successCode" is the code to run once we have successfully done the conversion. The resulting string should be used with string.Template, it needs the following keys when substituting: jsvalPtr/jsvalRef/obj. + + Returns (templateString, infallibility of conversion template) """ haveSuccessCode = successCode is not None if not haveSuccessCode: @@ -2442,7 +2444,7 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode, return str if type is None or type.isVoid(): - return setValue("JSVAL_VOID") + return (setValue("JSVAL_VOID"), True) if type.isArray(): raise TypeError("Can't handle array return values yet") @@ -2450,14 +2452,14 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode, if type.isSequence(): if type.nullable(): # Nullable sequences are Nullable< nsTArray<T> > - return """ + (recTemplate, recInfall) = getWrapTemplateForType(type.inner, descriptorProvider, + "%s.Value()" % result, successCode, + isCreator) + return (""" if (%s.IsNull()) { %s } -%s""" % (result, CGIndenter(CGGeneric(setValue("JSVAL_NULL"))).define(), - getWrapTemplateForType(type.inner, descriptorProvider, - "%s.Value()" % result, successCode, - isCreator)) +%s""" % (result, CGIndenter(CGGeneric(setValue("JSVAL_NULL"))).define(), recTemplate), recInfall) # Now do non-nullable sequences. We use setting the element # in the array as our succcess code because when we succeed in @@ -2476,7 +2478,7 @@ if (%s.IsNull()) { } ) innerTemplate = CGIndenter(CGGeneric(innerTemplate)).define() - return (""" + return ((""" uint32_t length = %s.Length(); JSObject *returnArray = JS_NewArrayObject(cx, length, NULL); if (!returnArray) { @@ -2485,7 +2487,7 @@ if (!returnArray) { jsval tmp; for (uint32_t i = 0; i < length; ++i) { %s -}\n""" % (result, innerTemplate)) + setValue("JS::ObjectValue(*returnArray)") +}\n""" % (result, innerTemplate)) + setValue("JS::ObjectValue(*returnArray)"), False) if type.isGeckoInterface(): descriptor = descriptorProvider.getDescriptor(type.unroll().inner.identifier.name) @@ -2527,26 +2529,27 @@ for (uint32_t i = 0; i < length; ++i) { getIID = "" wrap = "WrapObject(cx, ${obj}, %s, %s${jsvalPtr})" % (result, getIID) wrappingCode += wrapAndSetPtr(wrap) - return wrappingCode + return (wrappingCode, False) if type.isString(): if type.nullable(): - return wrapAndSetPtr("xpc::StringToJsval(cx, %s, ${jsvalPtr})" % result) + return (wrapAndSetPtr("xpc::StringToJsval(cx, %s, ${jsvalPtr})" % result), False) else: - return wrapAndSetPtr("xpc::NonVoidStringToJsval(cx, %s, ${jsvalPtr})" % result) + return (wrapAndSetPtr("xpc::NonVoidStringToJsval(cx, %s, ${jsvalPtr})" % result), False) if type.isEnum(): if type.nullable(): raise TypeError("We don't support nullable enumerated return types " "yet") - return """MOZ_ASSERT(uint32_t(%(result)s) < ArrayLength(%(strings)s)); + return ("""MOZ_ASSERT(uint32_t(%(result)s) < ArrayLength(%(strings)s)); JSString* %(resultStr)s = JS_NewStringCopyN(cx, %(strings)s[uint32_t(%(result)s)].value, %(strings)s[uint32_t(%(result)s)].length); if (!%(resultStr)s) { return false; } """ % { "result" : result, "resultStr" : result + "_str", - "strings" : type.inner.identifier.name + "Values::strings" } + setValue("JS::StringValue(%s_str)" % result) + "strings" : type.inner.identifier.name + "Values::strings" } + + setValue("JS::StringValue(%s_str)" % result), False) if type.isCallback(): assert not type.isInterface() @@ -2554,12 +2557,14 @@ if (!%(resultStr)s) { # nullable and always have [TreatNonCallableAsNull] for now. # See comments in WrapNewBindingObject explaining why we need # to wrap here. - return setValue("JS::ObjectOrNullValue(%s)" % result, True) + # NB: setValue(..., True) calls JS_WrapValue(), so is fallible + return (setValue("JS::ObjectOrNullValue(%s)" % result, True), False) if type.tag() == IDLType.Tags.any: # See comments in WrapNewBindingObject explaining why we need # to wrap here. - return setValue(result, True) + # NB: setValue(..., True) calls JS_WrapValue(), so is fallible + return (setValue(result, True), False) if type.isObject(): # See comments in WrapNewBindingObject explaining why we need @@ -2568,36 +2573,37 @@ if (!%(resultStr)s) { toValue = "JS::ObjectOrNullValue(%s)" else: toValue = "JS::ObjectValue(*%s)" - return setValue(toValue % result, True) + # NB: setValue(..., True) calls JS_WrapValue(), so is fallible + return (setValue(toValue % result, True), False) if not type.isPrimitive(): raise TypeError("Need to learn to wrap %s" % type) if type.nullable(): + (recTemplate, recInfal) = getWrapTemplateForType(type.inner, descriptorProvider, + "%s.Value()" % result, successCode, + isCreator) return ("if (%s.IsNull()) {\n" % result + CGIndenter(CGGeneric(setValue("JSVAL_NULL"))).define() + "\n" + - "}\n" + - getWrapTemplateForType(type.inner, descriptorProvider, - "%s.Value()" % result, successCode, - isCreator)) + "}\n" + recTemplate, recInfal) tag = type.tag() if tag in [IDLType.Tags.int8, IDLType.Tags.uint8, IDLType.Tags.int16, IDLType.Tags.uint16, IDLType.Tags.int32]: - return setValue("INT_TO_JSVAL(int32_t(%s))" % result) + return (setValue("INT_TO_JSVAL(int32_t(%s))" % result), True) elif tag in [IDLType.Tags.int64, IDLType.Tags.uint64, IDLType.Tags.float, IDLType.Tags.double]: # XXXbz will cast to double do the "even significand" thing that webidl # calls for for 64-bit ints? Do we care? - return setValue("JS_NumberValue(double(%s))" % result) + return (setValue("JS_NumberValue(double(%s))" % result), True) elif tag == IDLType.Tags.uint32: - return setValue("UINT_TO_JSVAL(%s)" % result) + return (setValue("UINT_TO_JSVAL(%s)" % result), True) elif tag == IDLType.Tags.bool: - return setValue("BOOLEAN_TO_JSVAL(%s)" % result) + return (setValue("BOOLEAN_TO_JSVAL(%s)" % result), True) else: raise TypeError("Need to learn to wrap primitive: %s" % type) @@ -2626,11 +2632,25 @@ def wrapForType(type, descriptorProvider, templateValues): wrap = getWrapTemplateForType(type, descriptorProvider, templateValues.get('result', 'result'), templateValues.get('successCode', None), - templateValues.get('isCreator', False)) + templateValues.get('isCreator', False))[0] defaultValues = {'obj': 'obj'} return string.Template(wrap).substitute(defaultValues, **templateValues) +def infallibleForAttr(attr, descriptorProvider): + """ + Determine the fallibility of changing a C++ value of IDL type "type" into + JS for the given attribute. Apart from isCreator, all the defaults are used, + since the fallbility does not change based on the boolean values, + and the template will be discarded. + + CURRENT ASSUMPTIONS: + We assume that successCode for wrapping up return values cannot contain + failure conditions. + """ + return getWrapTemplateForType(attr.type, descriptorProvider, 'result', None,\ + memberIsCreator(attr))[1] + def typeNeedsCx(type): return (type is not None and (type.isCallback() or type.isAny() or type.isObject() or @@ -2825,7 +2845,7 @@ class CGPerSignatureCall(CGThing): return not 'infallible' in self.extendedAttributes def wrap_return_value(self): - isCreator = self.idlNode.getExtendedAttribute("Creator") is not None + isCreator = memberIsCreator(self.idlNode) if isCreator: # We better be returning addrefed things! assert isResultAlreadyAddRefed(self.descriptor, @@ -3365,6 +3385,9 @@ class CGSpecializedSetter(CGAbstractStaticMethod): return CGIndenter(CGSetterCall(self.attr.type, nativeName, self.descriptor, self.attr)).define() +def memberIsCreator(member): + return member.getExtendedAttribute("Creator") is not None + class CGPropertyJITInfo(CGThing): """ A class for generating the JITInfo for a property that points to @@ -3394,9 +3417,9 @@ class CGPropertyJITInfo(CGThing): getterinfo = ("%s_getterinfo" % self.attr.identifier.name) getter = ("(JSJitPropertyOp)specialized_get_%s" % self.attr.identifier.name) - # For now, mark all getters fallible, until argument wrapping has been - # handled. - result = self.defineJitInfo(getterinfo, getter, False) + getterinfal = "infallible" in self.descriptor.getExtendedAttributes(self.attr, getter=True) + getterinfal = getterinfal and infallibleForAttr(self.attr, self.descriptor) + result = self.defineJitInfo(getterinfo, getter, getterinfal) if not self.attr.readonly: setterinfo = ("%s_setterinfo" % self.attr.identifier.name) setter = ("(JSJitPropertyOp)specialized_set_%s" % From 10c9046c35c96b7add138e6f6390591d4cd443a5 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky <bzbarsky@mit.edu> Date: Tue, 7 Aug 2012 22:26:18 -0700 Subject: [PATCH 133/169] Bug 747287 - Part 3: Add callback interface to allow JIT to interrogate DOM. (r=peterv) --- dom/base/nsJSEnvironment.cpp | 6 +++++- dom/bindings/BindingUtils.cpp | 19 ++++++++++++++++++- dom/bindings/BindingUtils.h | 11 ++++++++++- dom/bindings/Codegen.py | 5 ++++- dom/bindings/DOMJSClass.h | 5 +++++ js/src/jsapi.cpp | 1 + js/src/jscntxt.h | 1 + js/src/jsfriendapi.cpp | 12 ++++++++++++ js/src/jsfriendapi.h | 15 +++++++++++++++ 9 files changed, 71 insertions(+), 4 deletions(-) diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index a7c68a337a07..d8629b9243d7 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -3958,7 +3958,6 @@ SourceHook(JSContext *cx, JSScript *script, jschar **src, uint32_t *length) return true; } - //static nsresult nsJSRuntime::Init() @@ -4012,6 +4011,11 @@ nsJSRuntime::Init() }; JS_SetStructuredCloneCallbacks(sRuntime, &cloneCallbacks); + static js::DOMCallbacks DOMcallbacks = { + InstanceClassHasProtoAtDepth + }; + SetDOMCallbacks(sRuntime, &DOMcallbacks); + // Set these global xpconnect options... Preferences::RegisterCallback(MaxScriptRunTimePrefChangedCallback, "dom.max_script_run_time"); diff --git a/dom/bindings/BindingUtils.cpp b/dom/bindings/BindingUtils.cpp index f2dd4a2783f5..6a9f5b89ebdd 100644 --- a/dom/bindings/BindingUtils.cpp +++ b/dom/bindings/BindingUtils.cpp @@ -242,7 +242,8 @@ JSObject* CreateInterfaceObjects(JSContext* cx, JSObject* global, JSObject *receiver, JSObject* protoProto, JSClass* protoClass, JSClass* constructorClass, JSNative constructor, - unsigned ctorNargs, Prefable<JSFunctionSpec>* methods, + unsigned ctorNargs, JSClass* instanceClass, + Prefable<JSFunctionSpec>* methods, Prefable<JSPropertySpec>* properties, Prefable<ConstantSpec>* constants, Prefable<JSFunctionSpec>* staticMethods, const char* name) @@ -264,6 +265,9 @@ CreateInterfaceObjects(JSContext* cx, JSObject* global, JSObject *receiver, if (!proto) { return NULL; } + + js::SetReservedSlot(proto, DOM_PROTO_INSTANCE_CLASS_SLOT, + JS::PrivateValue(instanceClass)); } else { proto = NULL; @@ -323,6 +327,19 @@ DoHandleNewBindingWrappingFailure(JSContext* cx, JSObject* scope, return Throw<true>(cx, NS_ERROR_XPC_BAD_CONVERT_JS); } +// Can only be called with the immediate prototype of the instance object. Can +// only be called on the prototype of an object known to be a DOM instance. +JSBool +InstanceClassHasProtoAtDepth(JSHandleObject protoObject, uint32_t protoID, + uint32_t depth) +{ + JSClass* instanceClass = static_cast<JSClass*>( + js::GetReservedSlot(protoObject, DOM_PROTO_INSTANCE_CLASS_SLOT).toPrivate()); + MOZ_ASSERT(IsDOMClass(instanceClass)); + DOMJSClass* domClass = DOMJSClass::FromJSClass(instanceClass); + return domClass->mInterfaceChain[depth] == protoID; +} + // Only set allowNativeWrapper to false if you really know you need it, if in // doubt use true. Setting it to false disables security wrappers. bool diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h index a00e199e3dcb..385aa65269f8 100644 --- a/dom/bindings/BindingUtils.h +++ b/dom/bindings/BindingUtils.h @@ -287,6 +287,8 @@ struct Prefable { * object of constructorClass, unless that's also null, in which * case we should not create an interface object at all. * ctorNargs is the length of the constructor function; 0 if no constructor + * instanceClass is the JSClass of instance objects for this class. This can + * be null if this is not a concrete proto. * methods and properties are to be defined on the interface prototype object; * these arguments are allowed to be null if there are no * methods or properties respectively. @@ -307,7 +309,8 @@ JSObject* CreateInterfaceObjects(JSContext* cx, JSObject* global, JSObject* receiver, JSObject* protoProto, JSClass* protoClass, JSClass* constructorClass, JSNative constructor, - unsigned ctorNargs, Prefable<JSFunctionSpec>* methods, + unsigned ctorNargs, JSClass* instanceClass, + Prefable<JSFunctionSpec>* methods, Prefable<JSPropertySpec>* properties, Prefable<ConstantSpec>* constants, Prefable<JSFunctionSpec>* staticMethods, const char* name); @@ -552,6 +555,12 @@ GetParentPointer(const ParentObject& aObject) return ToSupports(aObject.mObject); } +// Can only be called with the immediate prototype of the instance object. Can +// only be called on the prototype of an object known to be a DOM instance. +JSBool +InstanceClassHasProtoAtDepth(JSHandleObject protoObject, uint32_t protoID, + uint32_t depth); + // Only set allowNativeWrapper to false if you really know you need it, if in // doubt use true. Setting it to false disables security wrappers. bool diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index a4681f24d790..77c144dc5c9c 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -138,7 +138,8 @@ class CGPrototypeJSClass(CGThing): def define(self): return """ static JSClass PrototypeClass = { - "%sPrototype", 0, + "%sPrototype", + JSCLASS_HAS_RESERVED_SLOTS(1), JS_PropertyStub, /* addProperty */ JS_PropertyStub, /* delProperty */ JS_PropertyStub, /* getProperty */ @@ -1125,12 +1126,14 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod): call = CGGeneric(("return dom::CreateInterfaceObjects(aCx, aGlobal, aReceiver, parentProto,\n" " %s, %s, %s, %d,\n" + " %s,\n" " %%(methods)s, %%(attrs)s, %%(consts)s, %%(staticMethods)s,\n" " %s);") % ( "&PrototypeClass" if needInterfacePrototypeObject else "NULL", "&InterfaceObjectClass" if needInterfaceObjectClass else "NULL", constructHook if needConstructor else "NULL", constructArgs, + "&Class.mBase" if self.descriptor.concrete else "NULL", '"' + self.descriptor.interface.identifier.name + '"' if needInterfaceObject else "NULL")) if self.properties.hasChromeOnly(): diff --git a/dom/bindings/DOMJSClass.h b/dom/bindings/DOMJSClass.h index 62b617bf1fd3..12579cee2499 100644 --- a/dom/bindings/DOMJSClass.h +++ b/dom/bindings/DOMJSClass.h @@ -23,6 +23,11 @@ // We use these flag bits for the new bindings. #define JSCLASS_DOM_GLOBAL JSCLASS_USERBIT1 +// NOTE: This is baked into the Ion JIT as 0 in codegen for LGetDOMProperty and +// LSetDOMProperty. Those constants need to be changed accordingly if this value +// changes. +#define DOM_PROTO_INSTANCE_CLASS_SLOT 0 + namespace mozilla { namespace dom { diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 9ad2fcc55fc0..793a8ec46688 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -829,6 +829,7 @@ JSRuntime::JSRuntime() defaultFreeOp_(thisFromCtor(), false, false), debuggerMutations(0), securityCallbacks(const_cast<JSSecurityCallbacks *>(&NullSecurityCallbacks)), + DOMcallbacks(NULL), destroyPrincipals(NULL), structuredCloneCallbacks(NULL), telemetryCallback(NULL), diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index c5fa3ef8b5b3..49ec5cc5403c 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -790,6 +790,7 @@ struct JSRuntime : js::RuntimeFriendFields uint32_t debuggerMutations; const JSSecurityCallbacks *securityCallbacks; + const js::DOMCallbacks *DOMcallbacks; JSDestroyPrincipalsOp destroyPrincipals; /* Structured data callbacks are runtime-wide. */ diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp index fe73555efcc7..b1de6babca8e 100644 --- a/js/src/jsfriendapi.cpp +++ b/js/src/jsfriendapi.cpp @@ -922,6 +922,18 @@ EnableRuntimeProfilingStack(JSRuntime *rt, bool enabled) rt->spsProfiler.enable(enabled); } +JS_FRIEND_API(void) +SetDOMCallbacks(JSRuntime *rt, const DOMCallbacks *callbacks) +{ + rt->DOMcallbacks = callbacks; +} + +JS_FRIEND_API(const DOMCallbacks *) +GetDOMCallbacks(JSRuntime *rt) +{ + return rt->DOMcallbacks; +} + static void *gListBaseHandlerFamily = NULL; static uint32_t gListBaseExpandoSlot = 0; diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index 7a8e30ac55c5..c498a70495b5 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -736,6 +736,21 @@ SetGCSliceCallback(JSRuntime *rt, GCSliceCallback callback); extern JS_FRIEND_API(bool) WasIncrementalGC(JSRuntime *rt); +typedef JSBool +(* DOMInstanceClassMatchesProto)(JSHandleObject protoObject, uint32_t protoID, + uint32_t depth); + +struct JSDOMCallbacks { + DOMInstanceClassMatchesProto instanceClassMatchesProto; +}; +typedef struct JSDOMCallbacks DOMCallbacks; + +extern JS_FRIEND_API(void) +SetDOMCallbacks(JSRuntime *rt, const DOMCallbacks *callbacks); + +extern JS_FRIEND_API(const DOMCallbacks *) +GetDOMCallbacks(JSRuntime *rt); + /* * Signals a good place to do an incremental slice, because the browser is * drawing a frame. From d50fdfb27d8f645c0ba50f06c70b954bc7e7bce0 Mon Sep 17 00:00:00 2001 From: Eric Faust <efaust@mozilla.com> Date: Tue, 7 Aug 2012 22:26:19 -0700 Subject: [PATCH 134/169] Bug 773548 - Part 1: Modify Paris bindings to specialize methods. (r=peterv) --- dom/bindings/Codegen.py | 71 +++++++++++++++++++++++++++++------------ 1 file changed, 51 insertions(+), 20 deletions(-) diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index 77c144dc5c9c..0d52feecdb57 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -3268,11 +3268,30 @@ class CGNativeMethod(CGAbstractBindingMethod): args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'), Argument('JS::Value*', 'vp')] CGAbstractBindingMethod.__init__(self, descriptor, baseName, args) + def generate_code(self): + return CGIndenter(CGGeneric( + "return specialized_%s(cx, obj, self, argc, vp);" % + self.method.identifier.name)) + +class CGSpecializedMethod(CGAbstractStaticMethod): + """ + A class for generating the C++ code for a specialized method that the JIT + can call with lower overhead. + """ + def __init__(self, descriptor, method): + self.method = method + name = 'specialized_' + method.identifier.name + args = [Argument('JSContext*', 'cx'), Argument('JSHandleObject', 'obj'), + Argument('%s*' % descriptor.nativeType, 'self'), + Argument('unsigned', 'argc'), Argument('JS::Value*', 'vp')] + CGAbstractStaticMethod.__init__(self, descriptor, name, 'bool', args) + + def definition_body(self): name = self.method.identifier.name nativeName = MakeNativeName(self.descriptor.binaryNames.get(name, name)) return CGMethodCall([], nativeName, self.method.isStatic(), - self.descriptor, self.method) + self.descriptor, self.method).define() class CGNativeGetter(CGAbstractBindingMethod): """ @@ -3391,13 +3410,13 @@ class CGSpecializedSetter(CGAbstractStaticMethod): def memberIsCreator(member): return member.getExtendedAttribute("Creator") is not None -class CGPropertyJITInfo(CGThing): +class CGMemberJITInfo(CGThing): """ A class for generating the JITInfo for a property that points to our specialized getter and setter. """ - def __init__(self, descriptor, attr): - self.attr = attr + def __init__(self, descriptor, member): + self.member = member self.descriptor = descriptor def declare(self): @@ -3412,24 +3431,34 @@ class CGPropertyJITInfo(CGThing): " %s,\n" " %s,\n" " %s,\n" - " %s, /* isInfallible. False for setters. */\n" - " false /* isConstant. False for setters. */\n" + " %s, /* isInfallible. Only relevant for getters. */\n" + " false /* isConstant. Only relevant for getters. */\n" "};\n" % (infoName, opName, protoID, depth, failstr)) def define(self): - getterinfo = ("%s_getterinfo" % self.attr.identifier.name) - getter = ("(JSJitPropertyOp)specialized_get_%s" % - self.attr.identifier.name) - getterinfal = "infallible" in self.descriptor.getExtendedAttributes(self.attr, getter=True) - getterinfal = getterinfal and infallibleForAttr(self.attr, self.descriptor) - result = self.defineJitInfo(getterinfo, getter, getterinfal) - if not self.attr.readonly: - setterinfo = ("%s_setterinfo" % self.attr.identifier.name) - setter = ("(JSJitPropertyOp)specialized_set_%s" % - self.attr.identifier.name) - # Setters are always fallible, since they have to do a typed unwrap. - result += self.defineJitInfo(setterinfo, setter, False) - return result + if self.member.isAttr(): + getterinfo = ("%s_getterinfo" % self.member.identifier.name) + getter = ("(JSJitPropertyOp)specialized_get_%s" % + self.member.identifier.name) + getterinfal = "infallible" in self.descriptor.getExtendedAttributes(self.member, getter=True) + getterinfal = getterinfal and infallibleForAttr(self.member, self.descriptor) + result = self.defineJitInfo(getterinfo, getter, getterinfal) + if not self.member.readonly: + setterinfo = ("%s_setterinfo" % self.member.identifier.name) + setter = ("(JSJitPropertyOp)specialized_set_%s" % + self.member.identifier.name) + # Setters are always fallible, since they have to do a typed unwrap. + result += self.defineJitInfo(setterinfo, setter, False) + return result + if self.member.isMethod(): + methodinfo = ("%s_methodinfo" % self.member.identifier.name) + #XXXefaust Should be JSJitMethodOp, after centralization, but lazy for now + method = ("(JSJitPropertyOp)specialized_%s" % + self.member.identifier.name) + # Method, much like setters, are always fallible + result = self.defineJitInfo(methodinfo, method, False) + return result + raise TypeError("Illegal member type to CGPropertyJITInfo") def getEnumValueName(value): # Some enum values can be empty strings. Others might have weird @@ -4169,14 +4198,16 @@ class CGDescriptor(CGThing): if descriptor.interface.hasInterfacePrototypeObject(): for m in descriptor.interface.members: if m.isMethod() and not m.isStatic(): + cgThings.append(CGSpecializedMethod(descriptor, m)) cgThings.append(CGNativeMethod(descriptor, m)) + cgThings.append(CGMemberJITInfo(descriptor, m)) elif m.isAttr(): cgThings.append(CGSpecializedGetter(descriptor, m)) cgThings.append(CGNativeGetter(descriptor, m)) if not m.readonly: cgThings.append(CGSpecializedSetter(descriptor, m)) cgThings.append(CGNativeSetter(descriptor, m)) - cgThings.append(CGPropertyJITInfo(descriptor, m)) + cgThings.append(CGMemberJITInfo(descriptor, m)) if descriptor.concrete: if not descriptor.workers and descriptor.wrapperCache: From a2abc41ee280277c45d12783d2f28ccd4cd90c8f Mon Sep 17 00:00:00 2001 From: Eric Faust <efaust@mozilla.com> Date: Tue, 7 Aug 2012 22:26:19 -0700 Subject: [PATCH 135/169] Bug 775788 - Modify JSFunctionSpec to accept JSJitInfos. (r=luke) --- caps/src/nsSecurityManagerFactory.cpp | 4 +-- dom/base/nsJSEnvironment.cpp | 16 +++++------ dom/bindings/BindingUtils.cpp | 2 +- ipc/testshell/XPCShellEnvironment.cpp | 30 ++++++++++---------- js/src/builtin/TestingFunctions.cpp | 2 +- js/src/ctypes/CTypes.cpp | 2 +- js/src/jsapi.cpp | 6 ++-- js/src/jsapi.h | 23 ++++++++++----- js/src/jsfriendapi.h | 2 ++ js/src/shell/js.cpp | 2 +- js/xpconnect/loader/mozJSComponentLoader.cpp | 12 ++++---- js/xpconnect/shell/xpcshell.cpp | 30 ++++++++++---------- js/xpconnect/src/XPCComponents.cpp | 8 +++--- 13 files changed, 76 insertions(+), 63 deletions(-) diff --git a/caps/src/nsSecurityManagerFactory.cpp b/caps/src/nsSecurityManagerFactory.cpp index 3ff887c63c28..8900ea959301 100644 --- a/caps/src/nsSecurityManagerFactory.cpp +++ b/caps/src/nsSecurityManagerFactory.cpp @@ -107,8 +107,8 @@ netscape_security_enablePrivilege(JSContext *cx, unsigned argc, jsval *vp) } static JSFunctionSpec PrivilegeManager_static_methods[] = { - { "enablePrivilege", netscape_security_enablePrivilege, 1,0}, - {nullptr,nullptr,0,0} + JS_FS("enablePrivilege", netscape_security_enablePrivilege, 1, 0), + JS_FS_END }; /* diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index d8629b9243d7..e84f7c248ec1 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -2612,14 +2612,14 @@ TraceMallocDumpAllocations(JSContext *cx, unsigned argc, jsval *vp) } static JSFunctionSpec TraceMallocFunctions[] = { - {"TraceMallocDisable", TraceMallocDisable, 0, 0}, - {"TraceMallocEnable", TraceMallocEnable, 0, 0}, - {"TraceMallocOpenLogFile", TraceMallocOpenLogFile, 1, 0}, - {"TraceMallocChangeLogFD", TraceMallocChangeLogFD, 1, 0}, - {"TraceMallocCloseLogFD", TraceMallocCloseLogFD, 1, 0}, - {"TraceMallocLogTimestamp", TraceMallocLogTimestamp, 1, 0}, - {"TraceMallocDumpAllocations", TraceMallocDumpAllocations, 1, 0}, - {nullptr, nullptr, 0, 0} + JS_FS("TraceMallocDisable", TraceMallocDisable, 0, 0), + JS_FS("TraceMallocEnable", TraceMallocEnable, 0, 0), + JS_FS("TraceMallocOpenLogFile", TraceMallocOpenLogFile, 1, 0), + JS_FS("TraceMallocChangeLogFD", TraceMallocChangeLogFD, 1, 0), + JS_FS("TraceMallocCloseLogFD", TraceMallocCloseLogFD, 1, 0), + JS_FS("TraceMallocLogTimestamp", TraceMallocLogTimestamp, 1, 0), + JS_FS("TraceMallocDumpAllocations", TraceMallocDumpAllocations, 1, 0), + JS_FS_END }; #endif /* NS_TRACE_MALLOC */ diff --git a/dom/bindings/BindingUtils.cpp b/dom/bindings/BindingUtils.cpp index 6a9f5b89ebdd..473c93b5486c 100644 --- a/dom/bindings/BindingUtils.cpp +++ b/dom/bindings/BindingUtils.cpp @@ -448,7 +448,7 @@ XrayResolveProperty(JSContext* cx, JSObject* wrapper, jsid id, size_t i = methods[prefIdx].specs - methodSpecs; for ( ; methodIds[i] != JSID_VOID; ++i) { if (id == methodIds[i]) { - JSFunction *fun = JS_NewFunctionById(cx, methodSpecs[i].call, + JSFunction *fun = JS_NewFunctionById(cx, methodSpecs[i].call.op, methodSpecs[i].nargs, 0, wrapper, id); if (!fun) diff --git a/ipc/testshell/XPCShellEnvironment.cpp b/ipc/testshell/XPCShellEnvironment.cpp index 86dc73d9b2e7..f51fdd14af18 100644 --- a/ipc/testshell/XPCShellEnvironment.cpp +++ b/ipc/testshell/XPCShellEnvironment.cpp @@ -492,21 +492,21 @@ DumpHeap(JSContext *cx, JSFunctionSpec gGlobalFunctions[] = { - {"print", Print, 0,0}, - {"load", Load, 1,0}, - {"quit", Quit, 0,0}, - {"version", Version, 1,0}, - {"build", BuildDate, 0,0}, - {"dumpXPC", DumpXPC, 1,0}, - {"dump", Dump, 1,0}, - {"gc", GC, 0,0}, -#ifdef JS_GC_ZEAL - {"gczeal", GCZeal, 1,0}, -#endif -#ifdef DEBUG - {"dumpHeap", DumpHeap, 5,0}, -#endif - {nullptr,nullptr,0,0} + JS_FS("print", Print, 0,0), + JS_FS("load", Load, 1,0), + JS_FS("quit", Quit, 0,0), + JS_FS("version", Version, 1,0), + JS_FS("build", BuildDate, 0,0), + JS_FS("dumpXPC", DumpXPC, 1,0), + JS_FS("dump", Dump, 1,0), + JS_FS("gc", GC, 0,0), + #ifdef JS_GC_ZEAL + JS_FS("gczeal", GCZeal, 1,0), + #endif + #ifdef DEBUG + JS_FS("dumpHeap", DumpHeap, 5,0), + #endif + JS_FS_END }; typedef enum JSShellErrNum diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index c7ab90ce2510..db4b8345495a 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -847,7 +847,7 @@ static JSFunctionSpecWithHelp TestingFunctions[] = { " Enables or disables the assertions related to SPS profiling. This is fairly\n" " expensive, so it shouldn't be enabled normally."), - JS_FS_END + JS_FS_HELP_END }; namespace js { diff --git a/js/src/ctypes/CTypes.cpp b/js/src/ctypes/CTypes.cpp index 683a1871cada..93dd33419e2f 100644 --- a/js/src/ctypes/CTypes.cpp +++ b/js/src/ctypes/CTypes.cpp @@ -832,7 +832,7 @@ InitTypeConstructor(JSContext* cx, MutableHandleObject typeProto, MutableHandleObject dataProto) { - JSFunction* fun = js::DefineFunctionWithReserved(cx, parent, spec.name, spec.call, + JSFunction* fun = js::DefineFunctionWithReserved(cx, parent, spec.name, spec.call.op, spec.nargs, spec.flags); if (!fun) return false; diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 793a8ec46688..0a07a3dff774 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -4977,7 +4977,7 @@ js_generic_native_method_dispatcher(JSContext *cx, unsigned argc, Value *vp) /* Clear the last parameter in case too few arguments were passed. */ vp[2 + --argc].setUndefined(); - return fs->call(cx, argc, vp); + return fs->call.op(cx, argc, vp); } JS_PUBLIC_API(JSBool) @@ -5025,9 +5025,11 @@ JS_DefineFunctions(JSContext *cx, JSObject *objArg, JSFunctionSpec *fs) fun->setExtendedSlot(0, PrivateValue(fs)); } - fun = js_DefineFunction(cx, obj, id, fs->call, fs->nargs, flags); + fun = js_DefineFunction(cx, obj, id, fs->call.op, fs->nargs, flags); if (!fun) return JS_FALSE; + if (fs->call.info) + fun->setJitInfo(fs->call.info); } return JS_TRUE; } diff --git a/js/src/jsapi.h b/js/src/jsapi.h index f1a904413296..5777d18985fa 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -4353,9 +4353,16 @@ typedef struct JSPropertyOpWrapper { } JSPropertyOpWrapper; /* - * Macro static initializers which correspond to the old |op| and |NULL| - * respectively, and make it easy to pass no JSJitInfo as part of a - * JSPropertySpec. + * Wrapper to do as above, but for JSNatives for JSFunctionSpecs. + */ +typedef struct JSNativeWrapper { + JSNative op; + const JSJitInfo *info; +} JSNativeWrapper; + +/* + * Macro static initializers which make it easy to pass no JSJitInfo as part of a + * JSPropertySpec or JSFunctionSpec. */ #define JSOP_WRAPPER(op) {op, NULL} #define JSOP_NULLWRAPPER JSOP_WRAPPER(NULL) @@ -4375,7 +4382,7 @@ struct JSPropertySpec { struct JSFunctionSpec { const char *name; - JSNative call; + JSNativeWrapper call; uint16_t nargs; uint16_t flags; }; @@ -4389,12 +4396,14 @@ struct JSFunctionSpec { /* * Initializer macros for a JSFunctionSpec array element. JS_FN (whose name * pays homage to the old JSNative/JSFastNative split) simply adds the flag - * JSFUN_STUB_GSOPS. + * JSFUN_STUB_GSOPS. JS_FNINFO allows the simple adding of JSJitInfos. */ #define JS_FS(name,call,nargs,flags) \ - {name, call, nargs, flags} + {name, JSOP_WRAPPER(call), nargs, flags} #define JS_FN(name,call,nargs,flags) \ - {name, call, nargs, (flags) | JSFUN_STUB_GSOPS} + {name, JSOP_WRAPPER(call), nargs, (flags) | JSFUN_STUB_GSOPS} +#define JS_FNINFO(name,call,info,nargs,flags) \ + {name,{call,info},nargs,flags} extern JS_PUBLIC_API(JSObject *) JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto, diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index c498a70495b5..2c6e4f847482 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -159,6 +159,8 @@ struct JSFunctionSpecWithHelp { #define JS_FN_HELP(name,call,nargs,flags,usage,help) \ {name, call, nargs, (flags) | JSPROP_ENUMERATE | JSFUN_STUB_GSOPS, usage, help} +#define JS_FS_HELP_END \ + {NULL, NULL, 0, 0, NULL, NULL} extern JS_FRIEND_API(bool) JS_DefineFunctionsWithHelp(JSContext *cx, JSObject *obj, const JSFunctionSpecWithHelp *fs); diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 3bf7c03d074f..d302afec67f2 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -3817,7 +3817,7 @@ static JSFunctionSpecWithHelp shell_functions[] = { " rooting hazards. This is helpful to reduce the time taken when interpreting\n" " heavily numeric code."), - JS_FS_END + JS_FS_HELP_END }; #ifdef MOZ_PROFILING # define PROFILING_FUNCTION_COUNT 5 diff --git a/js/xpconnect/loader/mozJSComponentLoader.cpp b/js/xpconnect/loader/mozJSComponentLoader.cpp index 49fb6b99411c..4b28921a2ab6 100644 --- a/js/xpconnect/loader/mozJSComponentLoader.cpp +++ b/js/xpconnect/loader/mozJSComponentLoader.cpp @@ -271,12 +271,12 @@ File(JSContext *cx, unsigned argc, jsval *vp) } static JSFunctionSpec gGlobalFun[] = { - {"dump", Dump, 1,0}, - {"debug", Debug, 1,0}, - {"atob", Atob, 1,0}, - {"btoa", Btoa, 1,0}, - {"File", File, 1,JSFUN_CONSTRUCTOR}, - {nullptr,nullptr,0,0} + JS_FS("dump", Dump, 1,0), + JS_FS("debug", Debug, 1,0), + JS_FS("atob", Atob, 1,0), + JS_FS("btoa", Btoa, 1,0), + JS_FS("File", File, 1,JSFUN_CONSTRUCTOR), + JS_FS_END }; class JSCLContextHelper diff --git a/js/xpconnect/shell/xpcshell.cpp b/js/xpconnect/shell/xpcshell.cpp index 3370f70a16ff..586d79f2507a 100644 --- a/js/xpconnect/shell/xpcshell.cpp +++ b/js/xpconnect/shell/xpcshell.cpp @@ -786,26 +786,26 @@ Parent(JSContext *cx, unsigned argc, jsval *vp) } static JSFunctionSpec glob_functions[] = { - {"print", Print, 0,0}, - {"readline", ReadLine, 1,0}, - {"load", Load, 1,0}, - {"quit", Quit, 0,0}, - {"version", Version, 1,0}, - {"build", BuildDate, 0,0}, - {"dumpXPC", DumpXPC, 1,0}, - {"dump", Dump, 1,0}, - {"gc", GC, 0,0}, + JS_FS("print", Print, 0,0), + JS_FS("readline", ReadLine, 1,0), + JS_FS("load", Load, 1,0), + JS_FS("quit", Quit, 0,0), + JS_FS("version", Version, 1,0), + JS_FS("build", BuildDate, 0,0), + JS_FS("dumpXPC", DumpXPC, 1,0), + JS_FS("dump", Dump, 1,0), + JS_FS("gc", GC, 0,0), #ifdef JS_GC_ZEAL - {"gczeal", GCZeal, 1,0}, + JS_FS("gczeal", GCZeal, 1,0), #endif - {"options", Options, 0,0}, + JS_FS("options", Options, 0,0), JS_FN("parent", Parent, 1,0), #ifdef DEBUG - {"dumpHeap", DumpHeap, 5,0}, + JS_FS("dumpHeap", DumpHeap, 5,0), #endif - {"sendCommand", SendCommand, 1,0}, - {"getChildGlobalObject", GetChildGlobalObject, 0,0}, - {nullptr,nullptr,0,0} + JS_FS("sendCommand", SendCommand, 1,0), + JS_FS("getChildGlobalObject", GetChildGlobalObject, 0,0), + JS_FS_END }; JSClass global_class = { diff --git a/js/xpconnect/src/XPCComponents.cpp b/js/xpconnect/src/XPCComponents.cpp index 87f473c844f2..1a0a5a8327b6 100644 --- a/js/xpconnect/src/XPCComponents.cpp +++ b/js/xpconnect/src/XPCComponents.cpp @@ -3002,10 +3002,10 @@ static JSClass SandboxClass = { }; static JSFunctionSpec SandboxFunctions[] = { - {"dump", SandboxDump, 1,0}, - {"debug", SandboxDebug, 1,0}, - {"importFunction", SandboxImport, 1,0}, - {nullptr,nullptr,0,0} + JS_FS("dump", SandboxDump, 1,0), + JS_FS("debug", SandboxDebug, 1,0), + JS_FS("importFunction", SandboxImport, 1,0), + JS_FS_END }; /***************************************************************************/ From 429e3ddab26eb47f0da19451d4a210aa4a1a32b6 Mon Sep 17 00:00:00 2001 From: Eric Faust <efaust@mozilla.com> Date: Tue, 7 Aug 2012 22:26:19 -0700 Subject: [PATCH 136/169] Bug 773548 - Part 2: Pass the generated JSJitInfos into JSFunctionSpec. (r=peterv) --- dom/bindings/Codegen.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index 0d52feecdb57..bc72777bf6c0 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -933,11 +933,13 @@ class MethodDefiner(PropertyDefiner): return m["pref"] def specData(m): - return (m["name"], m["name"], m["length"], m["flags"]) + hasInfo = (m["name"] != 'QueryInterface') + jitinfo = ("&%s_methodinfo" % m["name"]) if hasInfo else "NULL" + return (m["name"], m["name"], jitinfo, m["length"], m["flags"]) return self.generatePrefableArray( array, name, - ' JS_FN("%s", %s, %s, %s)', + ' JS_FNINFO("%s", %s, %s, %s, %s)', ' JS_FS_END', 'JSFunctionSpec', pref, specData, doIdArrays) From c0dee00d6ef0f0674549f1576cd47d8f3aeff0a6 Mon Sep 17 00:00:00 2001 From: Eric Faust <efaust@mozilla.com> Date: Tue, 7 Aug 2012 22:26:19 -0700 Subject: [PATCH 137/169] Bug 775289 - Remove generateNativeAccessors branching from Paris binding codegen. (r=peterv) --- dom/bindings/BindingGen.py | 4 -- dom/bindings/Codegen.py | 106 ++++++++----------------------------- dom/bindings/GlobalGen.py | 4 -- dom/bindings/Makefile.in | 15 ++---- 4 files changed, 25 insertions(+), 104 deletions(-) diff --git a/dom/bindings/BindingGen.py b/dom/bindings/BindingGen.py index 0f259c381d11..aa1337ea2a88 100644 --- a/dom/bindings/BindingGen.py +++ b/dom/bindings/BindingGen.py @@ -40,11 +40,7 @@ def main(): o = OptionParser(usage=usagestring) o.add_option("--verbose-errors", action='store_true', default=False, help="When an error happens, display the Python traceback.") - o.add_option("--use-jsop-accessors", action='store_true', default=False, - dest='useJSOPAccessors', - help="Use JSPropertyOps instead of JSNatives for getters and setters") (options, args) = o.parse_args() - Codegen.generateNativeAccessors = not options.useJSOPAccessors if len(args) != 4 or (args[0] != "header" and args[0] != "cpp"): o.error(usagestring) diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index bc72777bf6c0..59e230748226 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -956,12 +956,7 @@ class AttrDefiner(PropertyDefiner): return "" def flags(attr): - flags = "JSPROP_SHARED | JSPROP_ENUMERATE" - if generateNativeAccessors: - flags = "JSPROP_NATIVE_ACCESSORS | " + flags - elif attr.readonly: - return "JSPROP_READONLY | " + flags - return flags + return "JSPROP_SHARED | JSPROP_ENUMERATE | JSPROP_NATIVE_ACCESSORS" def getter(attr): return ("{(JSPropertyOp)get_%(name)s, &%(name)s_getterinfo}" @@ -3156,39 +3151,15 @@ class CGMethodCall(CGThing): def define(self): return self.cgRoot.define() -class CGGetterSetterCall(CGPerSignatureCall): - """ - A class to generate a native object getter or setter call for a - particular IDL getter or setter. - """ - def __init__(self, returnType, arguments, nativeMethodName, descriptor, - attr, getter=False, setter=False): - assert bool(getter) != bool(setter) - CGPerSignatureCall.__init__(self, returnType, [], arguments, - nativeMethodName, False, descriptor, attr, - getter=getter, setter=setter) - def getArgv(self): - if generateNativeAccessors: - return CGPerSignatureCall.getArgv(self) - return "vp" - -class CGGetterCall(CGGetterSetterCall): +class CGGetterCall(CGPerSignatureCall): """ A class to generate a native object getter call for a particular IDL getter. """ def __init__(self, returnType, nativeMethodName, descriptor, attr): - CGGetterSetterCall.__init__(self, returnType, [], nativeMethodName, - descriptor, attr, getter=True) - def getArgc(self): - if generateNativeAccessors: - return CGGetterSetterCall.getArgc() - return "0" - def getArgvDecl(self): - if generateNativeAccessors: - return CGPerSignatureCall.getArgvDecl(self) - # We just get our stuff from vp - return "" + CGPerSignatureCall.__init__(self, returnType, [], [], + nativeMethodName, False, descriptor, + attr, getter=True) class FakeArgument(): def __init__(self, type): @@ -3197,14 +3168,14 @@ class FakeArgument(): self.variadic = False self.defaultValue = None -class CGSetterCall(CGGetterSetterCall): +class CGSetterCall(CGPerSignatureCall): """ A class to generate a native object setter call for a particular IDL setter. """ def __init__(self, argType, nativeMethodName, descriptor, attr): - CGGetterSetterCall.__init__(self, None, [FakeArgument(argType)], - nativeMethodName, descriptor, attr, + CGPerSignatureCall.__init__(self, None, [], [FakeArgument(argType)], + nativeMethodName, False, descriptor, attr, setter=True) def wrap_return_value(self): # We have no return value @@ -3302,20 +3273,10 @@ class CGNativeGetter(CGAbstractBindingMethod): def __init__(self, descriptor, attr): self.attr = attr name = 'get_' + attr.identifier.name - if generateNativeAccessors: - args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'), - Argument('JS::Value*', 'vp')] - else: - args = [Argument('JSContext*', 'cx'), Argument('JSHandleObject', 'obj'), - Argument('JSHandleId', 'id'), Argument('JS::Value*', 'vp')] + args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'), + Argument('JS::Value*', 'vp')] CGAbstractBindingMethod.__init__(self, descriptor, name, args) - def getThis(self): - if generateNativeAccessors: - return CGAbstractBindingMethod.getThis(self) - return CGIndenter( - CGGeneric("%s* self;" % self.descriptor.nativeType)) - def generate_code(self): return CGIndenter(CGGeneric( "return specialized_get_%s(cx, obj, self, vp);" % @@ -3349,40 +3310,22 @@ class CGNativeSetter(CGAbstractBindingMethod): self.attr = attr baseName = attr.identifier.name name = 'set_' + attr.identifier.name - if generateNativeAccessors: - args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'), - Argument('JS::Value*', 'vp')] - else: - args = [Argument('JSContext*', 'cx'), Argument('JSHandleObject', 'obj'), - Argument('JSHandleId', 'id'), Argument('JSBool', 'strict'), - Argument('JS::Value*', 'vp')] + args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'), + Argument('JS::Value*', 'vp')] CGAbstractBindingMethod.__init__(self, descriptor, name, args) - def getThis(self): - if generateNativeAccessors: - return CGAbstractBindingMethod.getThis(self) - return CGIndenter( - CGGeneric("%s* self;" % self.descriptor.nativeType)) - def generate_code(self): - if generateNativeAccessors: - argv = ("JS::Value* argv = JS_ARGV(cx, vp);\n" - "jsval undef = JS::UndefinedValue();\n" - "if (argc == 0) {\n" - " argv = &undef;\n" - "}\n") - retval = "*vp = JSVAL_VOID;\n" - else: - argv = "JS::Value* argv = vp;\n" - retval = "" - return CGIndenter(CGGeneric( - argv + - ("if (!specialized_set_%s(cx, obj, self, argv)) {\n" + ("JS::Value* argv = JS_ARGV(cx, vp);\n" + "JS::Value undef = JS::UndefinedValue();\n" + "if (argc == 0) {\n" + " argv = &undef;\n" + "}\n" + "if (!specialized_set_%s(cx, obj, self, argv)) {\n" " return false;\n" "}\n" % self.attr.identifier.name) + - retval + - "return true;")) + "*vp = JSVAL_VOID;\n" + "return true;")) class CGSpecializedSetter(CGAbstractStaticMethod): """ @@ -3394,13 +3337,8 @@ class CGSpecializedSetter(CGAbstractStaticMethod): name = 'specialized_set_' + attr.identifier.name args = [ Argument('JSContext*', 'cx'), Argument('JSHandleObject', 'obj'), - Argument('%s*' % descriptor.nativeType, 'self') ] - # Our last argument is named differently depending on whether we're - # in the native accessors case or not - if generateNativeAccessors: - args.append(Argument('JS::Value*', 'argv')) - else: - args.append(Argument('JS::Value*', 'vp')) + Argument('%s*' % descriptor.nativeType, 'self'), + Argument('JS::Value*', 'argv')] CGAbstractStaticMethod.__init__(self, descriptor, name, "bool", args) def definition_body(self): diff --git a/dom/bindings/GlobalGen.py b/dom/bindings/GlobalGen.py index e07ea7c17dfb..2cad88bac8ca 100644 --- a/dom/bindings/GlobalGen.py +++ b/dom/bindings/GlobalGen.py @@ -39,11 +39,7 @@ def main(): help="Directory in which to cache lex/parse tables.") o.add_option("--verbose-errors", action='store_true', default=False, help="When an error happens, display the Python traceback.") - o.add_option("--use-jsop-accessors", action='store_true', default=False, - dest='useJSOPAccessors', - help="Use JSPropertyOps instead of JSNatives for getters and setters") (options, args) = o.parse_args() - Codegen.generateNativeAccessors = not options.useJSOPAccessors if len(args) < 2: o.error(usageString) diff --git a/dom/bindings/Makefile.in b/dom/bindings/Makefile.in index 606f3c5fa471..f091dd768d35 100644 --- a/dom/bindings/Makefile.in +++ b/dom/bindings/Makefile.in @@ -16,15 +16,6 @@ EXPORT_LIBRARY = 1 include $(topsrcdir)/config/config.mk -# Define USE_JSOP_ACCESSORS to a nonempty string like "yes" to use them -USE_JSOP_ACCESSORS = -ifdef USE_JSOP_ACCESSORS -DEFINES += -DUSE_JSOP_ACCESSORS -ACCESSOR_OPT = --use-jsop-accessors -else -ACCESSOR_OPT = -endif - # Need this to find all our DOM source files. include $(topsrcdir)/dom/dom-config.mk @@ -106,7 +97,7 @@ $(binding_header_files): %Binding.h: $(bindinggen_dependencies) \ $(NULL) PYTHONDONTWRITEBYTECODE=1 $(PYTHON) $(topsrcdir)/config/pythonpath.py \ $(PLY_INCLUDE) -I$(srcdir)/parser \ - $(srcdir)/BindingGen.py $(ACCESSOR_OPT) header \ + $(srcdir)/BindingGen.py header \ $(srcdir)/Bindings.conf $*Binding \ $*.webidl @@ -115,7 +106,7 @@ $(binding_cpp_files): %Binding.cpp: $(bindinggen_dependencies) \ $(NULL) PYTHONDONTWRITEBYTECODE=1 $(PYTHON) $(topsrcdir)/config/pythonpath.py \ $(PLY_INCLUDE) -I$(srcdir)/parser \ - $(srcdir)/BindingGen.py $(ACCESSOR_OPT) cpp \ + $(srcdir)/BindingGen.py cpp \ $(srcdir)/Bindings.conf $*Binding \ $*.webidl @@ -141,7 +132,7 @@ ParserResults.pkl: $(globalgen_dependencies) \ $(all_webidl_files) PYTHONDONTWRITEBYTECODE=1 $(PYTHON) $(topsrcdir)/config/pythonpath.py \ $(PLY_INCLUDE) -I$(srcdir)/parser \ - $(srcdir)/GlobalGen.py $(ACCESSOR_OPT) $(srcdir)/Bindings.conf . \ + $(srcdir)/GlobalGen.py $(srcdir)/Bindings.conf . \ --cachedir=$(CACHE_DIR) \ $(all_webidl_files) From 03db756eca70504da87177430a12a602b5a454af Mon Sep 17 00:00:00 2001 From: Eric Faust <efaust@mozilla.com> Date: Tue, 7 Aug 2012 22:26:19 -0700 Subject: [PATCH 138/169] Bug 773546 - Part 1: Punch an API hole to retrieve stored JSJitInfos. (r=luke) --- js/src/jsfriendapi.h | 24 ++++++++++++++++++++++-- js/src/jsfun.h | 4 ++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index 2c6e4f847482..b97185d0320d 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -325,6 +325,16 @@ struct Object { } }; +struct Function { + Object base; + uint16_t nargs; + uint16_t flahs; + /* Used only for natives */ + Native native; + const JSJitInfo *jitinfo; + void *_1; +}; + struct Atom { size_t _; const jschar *chars; @@ -1316,8 +1326,11 @@ JS_GetDataViewData(JSObject *obj, JSContext *cx); * available to general JSAPI users, but we are not currently ready to do so. */ typedef bool -(* JSJitPropertyOp)(JSContext *cx, JSObject *thisObj, +(* JSJitPropertyOp)(JSContext *cx, JSHandleObject thisObj, void *specializedThis, JS::Value *vp); +typedef bool +(* JSJitMethodOp)(JSContext *cx, JSHandleObject thisObj, + void *specializedThis, unsigned argc, JS::Value *vp); struct JSJitInfo { JSJitPropertyOp op; @@ -1326,6 +1339,13 @@ struct JSJitInfo { bool isInfallible; /* Is op fallible? Getters only */ bool isConstant; /* Getting a construction-time constant? */ }; -#endif + +static JS_ALWAYS_INLINE const JSJitInfo * +FUNCTION_VALUE_TO_JITINFO(const JS::Value& v) +{ + JS_ASSERT(js::GetObjectClass(&v.toObject()) == &js::FunctionClass); + return reinterpret_cast<js::shadow::Function *>(&v.toObject())->jitinfo; +} +#endif /* __cplusplus */ #endif /* jsfriendapi_h___ */ diff --git a/js/src/jsfun.h b/js/src/jsfun.h index f22be354f2bf..7c29c2085a00 100644 --- a/js/src/jsfun.h +++ b/js/src/jsfun.h @@ -183,6 +183,10 @@ struct JSFunction : public JSObject bool setTypeForScriptedFunction(JSContext *cx, bool singleton = false); private: + static void staticAsserts() { + MOZ_STATIC_ASSERT(sizeof(JSFunction) == sizeof(js::shadow::Function), + "shadow interface must match actual interface"); + } /* * These member functions are inherited from JSObject, but should never be applied to * a value statically known to be a JSFunction. From c8a8c9afd6feefc8cb37e1edd8fcdd3680c20f23 Mon Sep 17 00:00:00 2001 From: Eric Faust <efaust@mozilla.com> Date: Tue, 7 Aug 2012 22:26:19 -0700 Subject: [PATCH 139/169] Bug 781040 - Fault in methods and accessors with JSJitinfos on ResolveProperty. (r=bz,benjamin) --- dom/bindings/BindingUtils.cpp | 31 ++++++++++++++++++++++++++++--- js/src/jsfriendapi.h | 11 ++++++++++- js/src/jsfun.h | 4 ++++ 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/dom/bindings/BindingUtils.cpp b/dom/bindings/BindingUtils.cpp index 473c93b5486c..0d037f96abcd 100644 --- a/dom/bindings/BindingUtils.cpp +++ b/dom/bindings/BindingUtils.cpp @@ -453,6 +453,7 @@ XrayResolveProperty(JSContext* cx, JSObject* wrapper, jsid id, wrapper, id); if (!fun) return false; + SET_JITINFO(fun, methodSpecs[i].call.info); JSObject *funobj = JS_GetFunctionObject(fun); desc->value.setObject(*funobj); desc->attrs = methodSpecs[i].flags; @@ -473,10 +474,34 @@ XrayResolveProperty(JSContext* cx, JSObject* wrapper, jsid id, size_t i = attributes[prefIdx].specs - attributeSpecs; for ( ; attributeIds[i] != JSID_VOID; ++i) { if (id == attributeIds[i]) { - desc->attrs = attributeSpecs[i].flags; + // Because of centralization, we need to make sure we fault in the + // JitInfos as well. At present, until the JSAPI changes, the easiest + // way to do this is wrap them up as functions ourselves. + desc->attrs = attributeSpecs[i].flags & ~JSPROP_NATIVE_ACCESSORS; + // They all have getters, so we can just make it. + JSObject *global = JS_GetGlobalForObject(cx, wrapper); + JSFunction *fun = JS_NewFunction(cx, (JSNative)attributeSpecs[i].getter.op, + 0, 0, global, NULL); + if (!fun) + return false; + SET_JITINFO(fun, attributeSpecs[i].getter.info); + JSObject *funobj = JS_GetFunctionObject(fun); + desc->getter = js::CastAsJSPropertyOp(funobj); + desc->attrs |= JSPROP_GETTER; + if (attributeSpecs[i].setter.op) { + // We have a setter! Make it. + fun = JS_NewFunction(cx, (JSNative)attributeSpecs[i].setter.op, + 1, 0, global, NULL); + if (!fun) + return false; + SET_JITINFO(fun, attributeSpecs[i].setter.info); + funobj = JS_GetFunctionObject(fun); + desc->setter = js::CastAsJSStrictPropertyOp(funobj); + desc->attrs |= JSPROP_SETTER; + } else { + desc->setter = NULL; + } desc->obj = wrapper; - desc->setter = attributeSpecs[i].setter.op; - desc->getter = attributeSpecs[i].getter.op; return true; } } diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index b97185d0320d..7a55b8427fa9 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -328,7 +328,7 @@ struct Object { struct Function { Object base; uint16_t nargs; - uint16_t flahs; + uint16_t flags; /* Used only for natives */ Native native; const JSJitInfo *jitinfo; @@ -1346,6 +1346,15 @@ FUNCTION_VALUE_TO_JITINFO(const JS::Value& v) JS_ASSERT(js::GetObjectClass(&v.toObject()) == &js::FunctionClass); return reinterpret_cast<js::shadow::Function *>(&v.toObject())->jitinfo; } + +static JS_ALWAYS_INLINE void +SET_JITINFO(JSFunction * func, const JSJitInfo *info) +{ + js::shadow::Function *fun = reinterpret_cast<js::shadow::Function *>(func); + /* JS_ASSERT(func->isNative()). 0x4000 is JSFUN_INTERPRETED */ + JS_ASSERT(!(fun->flags & 0x4000)); + fun->jitinfo = info; +} #endif /* __cplusplus */ #endif /* jsfriendapi_h___ */ diff --git a/js/src/jsfun.h b/js/src/jsfun.h index 7c29c2085a00..b3d0d9a9c56e 100644 --- a/js/src/jsfun.h +++ b/js/src/jsfun.h @@ -39,6 +39,10 @@ #define JSFUN_EXPR_CLOSURE 0x1000 /* expression closure: function(x) x*x */ #define JSFUN_EXTENDED 0x2000 /* structure is FunctionExtended */ +/* + * NB: JSFUN_INTERPRETED is hardcode duplicated in SET_JITINFO() in + * jsfriendapi.h. If it changes, it must also be updated there. + */ #define JSFUN_INTERPRETED 0x4000 /* use u.i if kind >= this value else u.native */ namespace js { class FunctionExtended; } From 8c6597d1c4ad1b8a540b5ec525e80ff198a00f76 Mon Sep 17 00:00:00 2001 From: Eric Faust <efaust@mozilla.com> Date: Tue, 7 Aug 2012 22:26:20 -0700 Subject: [PATCH 140/169] Bug 773546 - Part 2: Centralize Paris binding accessor and method top halves. (r=peterv) --- dom/bindings/Codegen.py | 96 ++++++++++++++++++++--------------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index 59e230748226..8d38fd1a22bd 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -933,9 +933,10 @@ class MethodDefiner(PropertyDefiner): return m["pref"] def specData(m): - hasInfo = (m["name"] != 'QueryInterface') - jitinfo = ("&%s_methodinfo" % m["name"]) if hasInfo else "NULL" - return (m["name"], m["name"], jitinfo, m["length"], m["flags"]) + isQI = (m["name"] == 'QueryInterface') + jitinfo = ("&%s_methodinfo" % m["name"]) if not isQI else "NULL" + accessor = "genericMethod" if not isQI else "QueryInterface" + return (m["name"], accessor, jitinfo, m["length"], m["flags"]) return self.generatePrefableArray( array, name, @@ -959,13 +960,13 @@ class AttrDefiner(PropertyDefiner): return "JSPROP_SHARED | JSPROP_ENUMERATE | JSPROP_NATIVE_ACCESSORS" def getter(attr): - return ("{(JSPropertyOp)get_%(name)s, &%(name)s_getterinfo}" + return ("{(JSPropertyOp)genericGetter, &%(name)s_getterinfo}" % {"name" : attr.identifier.name}) def setter(attr): if attr.readonly: return "JSOP_NULLWRAPPER" - return ("{(JSStrictPropertyOp)set_%(name)s, &%(name)s_setterinfo}" + return ("{(JSStrictPropertyOp)genericSetter, &%(name)s_setterinfo}" % {"name" : attr.identifier.name}) def specData(attr): @@ -3231,21 +3232,20 @@ class CGAbstractBindingMethod(CGAbstractStaticMethod): def MakeNativeName(name): return name[0].upper() + name[1:] -class CGNativeMethod(CGAbstractBindingMethod): +class CGGenericMethod(CGAbstractBindingMethod): """ A class for generating the C++ code for an IDL method.. """ - def __init__(self, descriptor, method): - self.method = method - baseName = method.identifier.name + def __init__(self, descriptor): args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'), Argument('JS::Value*', 'vp')] - CGAbstractBindingMethod.__init__(self, descriptor, baseName, args) + CGAbstractBindingMethod.__init__(self, descriptor, 'genericMethod', args) def generate_code(self): return CGIndenter(CGGeneric( - "return specialized_%s(cx, obj, self, argc, vp);" % - self.method.identifier.name)) + "const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n" + "JSJitMethodOp method = (JSJitMethodOp)info->op;\n" + "return method(cx, obj, self, argc, vp);")) class CGSpecializedMethod(CGAbstractStaticMethod): """ @@ -3254,7 +3254,7 @@ class CGSpecializedMethod(CGAbstractStaticMethod): """ def __init__(self, descriptor, method): self.method = method - name = 'specialized_' + method.identifier.name + name = method.identifier.name args = [Argument('JSContext*', 'cx'), Argument('JSHandleObject', 'obj'), Argument('%s*' % descriptor.nativeType, 'self'), Argument('unsigned', 'argc'), Argument('JS::Value*', 'vp')] @@ -3266,21 +3266,20 @@ class CGSpecializedMethod(CGAbstractStaticMethod): return CGMethodCall([], nativeName, self.method.isStatic(), self.descriptor, self.method).define() -class CGNativeGetter(CGAbstractBindingMethod): +class CGGenericGetter(CGAbstractBindingMethod): """ A class for generating the C++ code for an IDL attribute getter. """ - def __init__(self, descriptor, attr): - self.attr = attr - name = 'get_' + attr.identifier.name + def __init__(self, descriptor): args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'), Argument('JS::Value*', 'vp')] - CGAbstractBindingMethod.__init__(self, descriptor, name, args) + CGAbstractBindingMethod.__init__(self, descriptor, 'genericGetter', args) def generate_code(self): return CGIndenter(CGGeneric( - "return specialized_get_%s(cx, obj, self, vp);" % - self.attr.identifier.name)) + "const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n" + "JSJitPropertyOp getter = info->op;\n" + "return getter(cx, obj, self, vp);")) class CGSpecializedGetter(CGAbstractStaticMethod): """ @@ -3289,7 +3288,7 @@ class CGSpecializedGetter(CGAbstractStaticMethod): """ def __init__(self, descriptor, attr): self.attr = attr - name = 'specialized_get_' + attr.identifier.name + name = 'get_' + attr.identifier.name args = [ Argument('JSContext*', 'cx'), Argument('JSHandleObject', 'obj'), Argument('%s*' % descriptor.nativeType, 'self'), @@ -3302,30 +3301,29 @@ class CGSpecializedGetter(CGAbstractStaticMethod): return CGIndenter(CGGetterCall(self.attr.type, nativeName, self.descriptor, self.attr)).define() -class CGNativeSetter(CGAbstractBindingMethod): +class CGGenericSetter(CGAbstractBindingMethod): """ A class for generating the C++ code for an IDL attribute setter. """ - def __init__(self, descriptor, attr): - self.attr = attr - baseName = attr.identifier.name - name = 'set_' + attr.identifier.name + def __init__(self, descriptor): args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'), Argument('JS::Value*', 'vp')] - CGAbstractBindingMethod.__init__(self, descriptor, name, args) + CGAbstractBindingMethod.__init__(self, descriptor, 'genericSetter', args) def generate_code(self): return CGIndenter(CGGeneric( - ("JS::Value* argv = JS_ARGV(cx, vp);\n" - "JS::Value undef = JS::UndefinedValue();\n" - "if (argc == 0) {\n" - " argv = &undef;\n" - "}\n" - "if (!specialized_set_%s(cx, obj, self, argv)) {\n" - " return false;\n" - "}\n" % self.attr.identifier.name) + - "*vp = JSVAL_VOID;\n" - "return true;")) + "JS::Value* argv = JS_ARGV(cx, vp);\n" + "JS::Value undef = JS::UndefinedValue();\n" + "if (argc == 0) {\n" + " argv = &undef;\n" + "}\n" + "const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n" + "JSJitPropertyOp setter = info->op;\n" + "if (!setter(cx, obj, self, argv)) {\n" + " return false;\n" + "}\n" + "*vp = JSVAL_VOID;\n" + "return true;")) class CGSpecializedSetter(CGAbstractStaticMethod): """ @@ -3334,7 +3332,7 @@ class CGSpecializedSetter(CGAbstractStaticMethod): """ def __init__(self, descriptor, attr): self.attr = attr - name = 'specialized_set_' + attr.identifier.name + name = 'set_' + attr.identifier.name args = [ Argument('JSContext*', 'cx'), Argument('JSHandleObject', 'obj'), Argument('%s*' % descriptor.nativeType, 'self'), @@ -3378,23 +3376,20 @@ class CGMemberJITInfo(CGThing): def define(self): if self.member.isAttr(): getterinfo = ("%s_getterinfo" % self.member.identifier.name) - getter = ("(JSJitPropertyOp)specialized_get_%s" % - self.member.identifier.name) + getter = ("(JSJitPropertyOp)get_%s" % self.member.identifier.name) getterinfal = "infallible" in self.descriptor.getExtendedAttributes(self.member, getter=True) getterinfal = getterinfal and infallibleForAttr(self.member, self.descriptor) result = self.defineJitInfo(getterinfo, getter, getterinfal) if not self.member.readonly: setterinfo = ("%s_setterinfo" % self.member.identifier.name) - setter = ("(JSJitPropertyOp)specialized_set_%s" % - self.member.identifier.name) + setter = ("(JSJitPropertyOp)set_%s" % self.member.identifier.name) # Setters are always fallible, since they have to do a typed unwrap. result += self.defineJitInfo(setterinfo, setter, False) return result if self.member.isMethod(): methodinfo = ("%s_methodinfo" % self.member.identifier.name) - #XXXefaust Should be JSJitMethodOp, after centralization, but lazy for now - method = ("(JSJitPropertyOp)specialized_%s" % - self.member.identifier.name) + # Actually a JSJitMethodOp, but JSJitPropertyOp by struct definition. + method = ("(JSJitPropertyOp)%s" % self.member.identifier.name) # Method, much like setters, are always fallible result = self.defineJitInfo(methodinfo, method, False) return result @@ -4136,18 +4131,23 @@ class CGDescriptor(CGThing): cgThings = [] if descriptor.interface.hasInterfacePrototypeObject(): + hasMethod, hasGetter, hasSetter = False, False, False for m in descriptor.interface.members: if m.isMethod() and not m.isStatic(): cgThings.append(CGSpecializedMethod(descriptor, m)) - cgThings.append(CGNativeMethod(descriptor, m)) cgThings.append(CGMemberJITInfo(descriptor, m)) + hasMethod = True elif m.isAttr(): cgThings.append(CGSpecializedGetter(descriptor, m)) - cgThings.append(CGNativeGetter(descriptor, m)) + hasGetter = True if not m.readonly: cgThings.append(CGSpecializedSetter(descriptor, m)) - cgThings.append(CGNativeSetter(descriptor, m)) + hasSetter = True cgThings.append(CGMemberJITInfo(descriptor, m)) + if hasMethod: cgThings.append(CGGenericMethod(descriptor)) + if hasGetter: cgThings.append(CGGenericGetter(descriptor)) + if hasSetter: cgThings.append(CGGenericSetter(descriptor)) + if descriptor.concrete: if not descriptor.workers and descriptor.wrapperCache: From 698b67e339b25e80aab939c70ecc72e6c70012bd Mon Sep 17 00:00:00 2001 From: Eric Faust <efaust@mozilla.com> Date: Tue, 7 Aug 2012 22:57:07 -0700 Subject: [PATCH 141/169] Bug 747287 - Followup: Add cast to fix build. (r=me) --- dom/bindings/BindingUtils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dom/bindings/BindingUtils.cpp b/dom/bindings/BindingUtils.cpp index 0d037f96abcd..4a1fec3cbe23 100644 --- a/dom/bindings/BindingUtils.cpp +++ b/dom/bindings/BindingUtils.cpp @@ -337,7 +337,7 @@ InstanceClassHasProtoAtDepth(JSHandleObject protoObject, uint32_t protoID, js::GetReservedSlot(protoObject, DOM_PROTO_INSTANCE_CLASS_SLOT).toPrivate()); MOZ_ASSERT(IsDOMClass(instanceClass)); DOMJSClass* domClass = DOMJSClass::FromJSClass(instanceClass); - return domClass->mInterfaceChain[depth] == protoID; + return (uint32_t)domClass->mInterfaceChain[depth] == protoID; } // Only set allowNativeWrapper to false if you really know you need it, if in From 6a5b86abf853494ec43e3a81ec556b9231080bd0 Mon Sep 17 00:00:00 2001 From: Mike Hommey <mh+mozilla@glandium.org> Date: Wed, 8 Aug 2012 09:33:16 +0200 Subject: [PATCH 142/169] Bug 777379 - Ensure that default is always the default target. r=ted --- browser/installer/windows/Makefile.in | 1 + config/rules.mk | 1 + js/src/config/rules.mk | 1 + tools/update-packaging/Makefile.in | 1 + 4 files changed, 4 insertions(+) diff --git a/browser/installer/windows/Makefile.in b/browser/installer/windows/Makefile.in index c1e74b74224d..5657c9cac65d 100644 --- a/browser/installer/windows/Makefile.in +++ b/browser/installer/windows/Makefile.in @@ -58,6 +58,7 @@ else PPL_LOCALE_ARGS=$(call EXPAND_LOCALE_SRCDIR,browser/locales)/installer endif +.DEFAULT_GOAL := installer installer:: $(MAKE) -C .. installer-stage $(MAKE) $(CONFIG_DIR)/setup.exe diff --git a/config/rules.mk b/config/rules.mk index 43fc7632ffe9..b494376b5a10 100644 --- a/config/rules.mk +++ b/config/rules.mk @@ -1774,6 +1774,7 @@ libs export:: default all:: if test -d $(DIST)/bin ; then touch $(DIST)/bin/.purgecaches ; fi +.DEFAULT_GOAL ?= default ############################################################################# # Derived targets and dependencies diff --git a/js/src/config/rules.mk b/js/src/config/rules.mk index 43fc7632ffe9..b494376b5a10 100644 --- a/js/src/config/rules.mk +++ b/js/src/config/rules.mk @@ -1774,6 +1774,7 @@ libs export:: default all:: if test -d $(DIST)/bin ; then touch $(DIST)/bin/.purgecaches ; fi +.DEFAULT_GOAL ?= default ############################################################################# # Derived targets and dependencies diff --git a/tools/update-packaging/Makefile.in b/tools/update-packaging/Makefile.in index 9d35dafe3d35..792fd2ec93ea 100644 --- a/tools/update-packaging/Makefile.in +++ b/tools/update-packaging/Makefile.in @@ -35,6 +35,7 @@ endif MAR_BIN = $(LIBXUL_DIST)/host/bin/mar$(HOST_BIN_SUFFIX) MBSDIFF_BIN = $(LIBXUL_DIST)/host/bin/mbsdiff$(HOST_BIN_SUFFIX) +.DEFAULT_GOAL := full-update full-update:: complete-patch ifeq ($(OS_TARGET), WINNT) From e3dfe5f671a193ced869552b86d9e9fada26bfbd Mon Sep 17 00:00:00 2001 From: Mike Hommey <mh+mozilla@glandium.org> Date: Wed, 8 Aug 2012 09:33:31 +0200 Subject: [PATCH 143/169] Bug 780462 - Don't remove dist/bin/components when building, but remove dist/bin/chrome.manifest. r=khuey --- Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.in b/Makefile.in index 0076ada21aaf..66bd3b427c52 100644 --- a/Makefile.in +++ b/Makefile.in @@ -81,7 +81,7 @@ default alldep all:: $(topsrcdir)/configure config.status $(RM) -r $(DIST)/include $(RM) -r $(DIST)/private $(RM) -r $(DIST)/public - $(RM) -r $(DIST)/bin/components + $(RM) $(DIST)/chrome.manifest $(RM) -r _tests $(topsrcdir)/configure: $(topsrcdir)/configure.in From 02ea21508320b01b315092e580efb505b24ea6dc Mon Sep 17 00:00:00 2001 From: Aryeh Gregor <ayg@aryeh.name> Date: Wed, 1 Aug 2012 11:17:10 +0300 Subject: [PATCH 144/169] Bug 779442 - Fix a few more incorrect uses of nsresult; r=ehsan --- .../components/printingui/src/unixshared/nsPrintProgress.cpp | 2 +- image/src/imgStatusTracker.h | 2 +- toolkit/components/statusfilter/nsBrowserStatusFilter.cpp | 2 +- toolkit/components/url-classifier/nsUrlClassifierDBService.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/embedding/components/printingui/src/unixshared/nsPrintProgress.cpp b/embedding/components/printingui/src/unixshared/nsPrintProgress.cpp index e5b1d9f5f611..6724509c334e 100644 --- a/embedding/components/printingui/src/unixshared/nsPrintProgress.cpp +++ b/embedding/components/printingui/src/unixshared/nsPrintProgress.cpp @@ -137,7 +137,7 @@ NS_IMETHODIMP nsPrintProgress::RegisterListener(nsIWebProgressListener * listene listener->OnStateChange(nullptr, nullptr, nsIWebProgressListener::STATE_STOP, NS_OK); else { - listener->OnStatusChange(nullptr, nullptr, 0, m_pendingStatus.get()); + listener->OnStatusChange(nullptr, nullptr, NS_OK, m_pendingStatus.get()); if (m_pendingStateFlags != -1) listener->OnStateChange(nullptr, nullptr, m_pendingStateFlags, m_pendingStateValue); } diff --git a/image/src/imgStatusTracker.h b/image/src/imgStatusTracker.h index 8e01c0755797..25f6adb39406 100644 --- a/image/src/imgStatusTracker.h +++ b/image/src/imgStatusTracker.h @@ -151,7 +151,7 @@ private: // can't create a cycle. mozilla::image::Image* mImage; PRUint32 mState; - nsresult mImageStatus; + PRUint32 mImageStatus; bool mHadLastPart; }; diff --git a/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp b/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp index 63e96b9fbe71..5733cae78131 100644 --- a/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp +++ b/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp @@ -317,7 +317,7 @@ void nsBrowserStatusFilter::MaybeSendStatus() { if (mStatusIsDirty) { - mListener->OnStatusChange(nullptr, nullptr, 0, mStatusMsg.get()); + mListener->OnStatusChange(nullptr, nullptr, NS_OK, mStatusMsg.get()); mCurrentStatusMsg = mStatusMsg; mStatusIsDirty = false; } diff --git a/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp b/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp index ae3ad556a6db..e99e86f56e33 100644 --- a/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp +++ b/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp @@ -3591,7 +3591,7 @@ nsresult nsUrlClassifierStore::ReadPrefixes(FallibleTArray<PRUint32>& array, const PRUint8 *blobdomain = mAllPrefixGetStatement->AsSharedBlob(0, &size); if (!blobdomain || (size != DOMAIN_LENGTH)) - return false; + return NS_OK; domainval = *(reinterpret_cast<const PRUint32*>(blobdomain)); From f040f500c12808b4f3ecaa8daf041f6e3bf45fcc Mon Sep 17 00:00:00 2001 From: Aryeh Gregor <ayg@aryeh.name> Date: Fri, 27 Jul 2012 16:54:09 +0300 Subject: [PATCH 145/169] Bug 777292 - modules/libpref/, toolkit/: Remove conversions to nsresult that will always result in NS_SUCCEEDED; r=bsmedberg --- modules/libpref/src/Preferences.cpp | 6 +----- toolkit/components/downloads/nsDownloadManager.cpp | 4 ++-- toolkit/components/intl/nsCharsetMenu.cpp | 6 ++---- toolkit/xre/nsAppRunner.cpp | 5 +---- 4 files changed, 6 insertions(+), 15 deletions(-) diff --git a/modules/libpref/src/Preferences.cpp b/modules/libpref/src/Preferences.cpp index ed138f172eab..d1f89dffdae5 100644 --- a/modules/libpref/src/Preferences.cpp +++ b/modules/libpref/src/Preferences.cpp @@ -461,11 +461,7 @@ ReadExtensionPrefs(nsIFile *aFile) break; } - rv = PREF_ParseBuf(&ps, buffer, read); - if (NS_FAILED(rv)) { - NS_WARNING("Pref stream parse failed"); - break; - } + PREF_ParseBuf(&ps, buffer, read); } PREF_FinalizeParseState(&ps); } diff --git a/toolkit/components/downloads/nsDownloadManager.cpp b/toolkit/components/downloads/nsDownloadManager.cpp index 5b2d185feca3..f27a38c538ad 100644 --- a/toolkit/components/downloads/nsDownloadManager.cpp +++ b/toolkit/components/downloads/nsDownloadManager.cpp @@ -196,9 +196,9 @@ nsDownloadManager::RemoveAllDownloads() for (PRInt32 i = mCurrentDownloads.Count() - 1; i >= 0; --i) { nsRefPtr<nsDownload> dl = mCurrentDownloads[0]; - nsresult result; + nsresult result = NS_OK; if (dl->IsPaused() && GetQuitBehavior() != QUIT_AND_CANCEL) - result = mCurrentDownloads.RemoveObject(dl); + mCurrentDownloads.RemoveObject(dl); else result = CancelDownload(dl->mID); diff --git a/toolkit/components/intl/nsCharsetMenu.cpp b/toolkit/components/intl/nsCharsetMenu.cpp index de2a3f9e0824..076cb1dbdb87 100644 --- a/toolkit/components/intl/nsCharsetMenu.cpp +++ b/toolkit/components/intl/nsCharsetMenu.cpp @@ -1193,11 +1193,9 @@ nsresult nsCharsetMenu::AddCharsetToItemArray(nsTArray<nsMenuEntry*> *aArray, if (aArray != NULL) { if (aPlace < 0) { - res = aArray->AppendElement(item) != nullptr; - if (NS_FAILED(res)) goto done; + aArray->AppendElement(item); } else { - res = aArray->InsertElementsAt(aPlace, 1, item) != nullptr; - if (NS_FAILED(res)) goto done; + aArray->InsertElementsAt(aPlace, 1, item); } } diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index 0c3bd9bf1de4..bddb210cc810 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -803,11 +803,8 @@ nsXULAppInfo::InvalidateCachesOnRestart() return NS_ERROR_NOT_AVAILABLE; } static const char kInvalidationHeader[] = NS_LINEBREAK "InvalidateCaches=1" NS_LINEBREAK; - rv = PR_Write(fd, kInvalidationHeader, sizeof(kInvalidationHeader) - 1); + PR_Write(fd, kInvalidationHeader, sizeof(kInvalidationHeader) - 1); PR_Close(fd); - - if (NS_FAILED(rv)) - return rv; } return NS_OK; } From a90407104756b3f34ddaee11c22c85b4243b9aae Mon Sep 17 00:00:00 2001 From: Aryeh Gregor <ayg@aryeh.name> Date: Wed, 1 Aug 2012 11:17:51 +0300 Subject: [PATCH 146/169] Bug 778428 - Refcount arrays of nodes in editor/; r=ehsan --- editor/libeditor/html/nsHTMLEditRules.cpp | 2 +- editor/libeditor/html/nsHTMLEditor.cpp | 2 +- editor/libeditor/html/nsTableEditor.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/editor/libeditor/html/nsHTMLEditRules.cpp b/editor/libeditor/html/nsHTMLEditRules.cpp index 7725fc792a0a..77dff552c914 100644 --- a/editor/libeditor/html/nsHTMLEditRules.cpp +++ b/editor/libeditor/html/nsHTMLEditRules.cpp @@ -7625,7 +7625,7 @@ nsHTMLEditRules::RemoveEmptyNodes() NS_ENSURE_SUCCESS(res, res); nsCOMArray<nsINode> arrayOfEmptyNodes, arrayOfEmptyCites; - nsTArray<nsINode*> skipList; + nsTArray<nsCOMPtr<nsINode> > skipList; // check for empty nodes while (!iter->IsDone()) { diff --git a/editor/libeditor/html/nsHTMLEditor.cpp b/editor/libeditor/html/nsHTMLEditor.cpp index cad15f57c31b..c97f7509740d 100644 --- a/editor/libeditor/html/nsHTMLEditor.cpp +++ b/editor/libeditor/html/nsHTMLEditor.cpp @@ -3769,7 +3769,7 @@ nsHTMLEditor::CollapseAdjacentTextNodes(nsIDOMRange *aInRange) { NS_ENSURE_TRUE(aInRange, NS_ERROR_NULL_POINTER); nsAutoTxnsConserveSelection dontSpazMySelection(this); - nsTArray<nsIDOMNode*> textNodes; + nsTArray<nsCOMPtr<nsIDOMNode> > textNodes; // we can't actually do anything during iteration, so store the text nodes in an array // don't bother ref counting them because we know we can hold them for the // lifetime of this method diff --git a/editor/libeditor/html/nsTableEditor.cpp b/editor/libeditor/html/nsTableEditor.cpp index cff7392664e9..77b1dc262384 100644 --- a/editor/libeditor/html/nsTableEditor.cpp +++ b/editor/libeditor/html/nsTableEditor.cpp @@ -1306,7 +1306,7 @@ nsHTMLEditor::DeleteRow(nsIDOMElement *aTable, PRInt32 aRowIndex) // The list of cells we will change rowspan in // and the new rowspan values for each - nsTArray<nsIDOMElement*> spanCellList; + nsTArray<nsCOMPtr<nsIDOMElement> > spanCellList; nsTArray<PRInt32> newSpanList; // Scan through cells in row to do rowspan adjustments @@ -2144,7 +2144,7 @@ nsHTMLEditor::JoinTableCells(bool aMergeNonContiguousContents) } // The list of cells we will delete after joining - nsTArray<nsIDOMElement*> deleteList; + nsTArray<nsCOMPtr<nsIDOMElement> > deleteList; // 2nd pass: Do the joining and merging for (rowIndex = 0; rowIndex < rowCount; rowIndex++) From 3ef511b172da697641b8eddfbb8f95b031201996 Mon Sep 17 00:00:00 2001 From: David Rajchenbach-Teller <dteller@mozilla.com> Date: Tue, 7 Aug 2012 20:49:07 -0400 Subject: [PATCH 147/169] Bug 780498 - More general fix. r=nfroyd --- .../components/osfile/osfile_unix_front.jsm | 87 ++++++++----------- 1 file changed, 35 insertions(+), 52 deletions(-) diff --git a/toolkit/components/osfile/osfile_unix_front.jsm b/toolkit/components/osfile/osfile_unix_front.jsm index 33feb6da2270..85e12e0206da 100644 --- a/toolkit/components/osfile/osfile_unix_front.jsm +++ b/toolkit/components/osfile/osfile_unix_front.jsm @@ -335,22 +335,6 @@ UnixFile.copyfile(sourcePath, destPath, null, flags) ); }; - - // This implementation uses |copyfile(3)|, from the BSD library. - // Adding moving of hierarchies and/or attributes is just a flag - // away. - File.move = function movefile(sourcePath, destPath, options) { - // This implementation uses |copyfile(3)|, from the BSD library. - // It can move directory hierarchies. - options = options || noOptions; - let flags = Const.COPYFILE_DATA | Const.COPYFILE_MOVE; - if (options.noOverwrite) { - flags |= Const.COPYFILE_EXCL; - } - throw_on_negative("move", - UnixFile.copyfile(sourcePath, destPath, null, flags) - ); - }; } else { // If the OS does not implement file copying for us, we need to // implement it ourselves. For this purpose, we need to define @@ -474,36 +458,37 @@ pipe_write.dispose(); } }; - } else { - // Fallback implementation of pump for other Unix platforms. - pump = pump_userland; - } - - // Implement |copy| using |pump|. - // This implementation would require some work before being able to - // copy directories - File.copy = function copy(sourcePath, destPath, options) { - options = options || noOptions; - let source, dest; - let result; - try { - source = File.open(sourcePath); - if (options.noOverwrite) { - dest = File.open(destPath, {create:true}); - } else { - dest = File.open(destPath, {write:true}); - } - result = pump(source, dest, options); - } catch (x) { - if (dest) { - dest.close(); - } - if (source) { - source.close(); - } - throw x; + } else { + // Fallback implementation of pump for other Unix platforms. + pump = pump_userland; } - }; + + // Implement |copy| using |pump|. + // This implementation would require some work before being able to + // copy directories + File.copy = function copy(sourcePath, destPath, options) { + options = options || noOptions; + let source, dest; + let result; + try { + source = File.open(sourcePath); + if (options.noOverwrite) { + dest = File.open(destPath, {create:true}); + } else { + dest = File.open(destPath, {write:true}); + } + result = pump(source, dest, options); + } catch (x) { + if (dest) { + dest.close(); + } + if (source) { + source.close(); + } + throw x; + } + }; + } // End of definition of copy // Implement |move| using |rename| (wherever possible) or |copy| // (if files are on distinct devices). @@ -539,13 +524,11 @@ throw new File.Error(); } - // Otherwise, copy and remove. - File.copy(sourcePath, destPath, options); - // FIXME: Clean-up in case of copy error? - File.remove(sourcePath); - }; - - } // End of definition of copy/move + // Otherwise, copy and remove. + File.copy(sourcePath, destPath, options); + // FIXME: Clean-up in case of copy error? + File.remove(sourcePath); + }; /** * Iterate on one directory. From 254b25f375492f7ea72b08535e8a6e12daef945f Mon Sep 17 00:00:00 2001 From: David Rajchenbach-Teller <dteller@mozilla.com> Date: Tue, 7 Aug 2012 20:49:07 -0400 Subject: [PATCH 148/169] Bug 780498 - Test that OS.File.move removes original file. r=yoric --- .../osfile/tests/mochi/worker_test_osfile_front.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/toolkit/components/osfile/tests/mochi/worker_test_osfile_front.js b/toolkit/components/osfile/tests/mochi/worker_test_osfile_front.js index ce93834b39ae..b66925a16361 100644 --- a/toolkit/components/osfile/tests/mochi/worker_test_osfile_front.js +++ b/toolkit/components/osfile/tests/mochi/worker_test_osfile_front.js @@ -192,9 +192,18 @@ function test_move_file() ok(true, "test_move_file: Move complete"); - // 3. Check + // 3. Check that destination exists compare_files("test_move_file", src_file_name, tmp2_file_name); + // 4. Check that original file does not exist anymore + let exn; + try { + OS.File.open(tmp_file_name); + } catch (x) { + exn = x; + } + ok(!!exn, "test_move_file: Original file has been removed"); + ok(true, "test_move_file: Cleaning up"); OS.File.remove(tmp2_file_name); } From 706334a7b66ceb13d2baac2284b9d95df406a763 Mon Sep 17 00:00:00 2001 From: Michal Novotny <michal.novotny@gmail.com> Date: Wed, 8 Aug 2012 12:23:15 +0200 Subject: [PATCH 149/169] Bug 746920 - Uninitialised value use in nsDiskCacheMap::FlushRecords, r=hurley --- netwerk/cache/nsDiskCacheMap.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/netwerk/cache/nsDiskCacheMap.cpp b/netwerk/cache/nsDiskCacheMap.cpp index 5fbd5430eda9..5410258b5b7b 100644 --- a/netwerk/cache/nsDiskCacheMap.cpp +++ b/netwerk/cache/nsDiskCacheMap.cpp @@ -369,16 +369,18 @@ nsDiskCacheMap::ShrinkRecords() PRUint32 newRecordsPerBucket = oldRecordsPerBucket; while (maxUsage < (newRecordsPerBucket >> 1)) newRecordsPerBucket >>= 1; - if (newRecordsPerBucket < kMinRecordCount) - newRecordsPerBucket = kMinRecordCount; + if (newRecordsPerBucket < (kMinRecordCount / kBuckets)) + newRecordsPerBucket = (kMinRecordCount / kBuckets); + NS_ASSERTION(newRecordsPerBucket <= oldRecordsPerBucket, + "ShrinkRecords() can't grow records!"); if (newRecordsPerBucket == oldRecordsPerBucket) return NS_OK; // Move the buckets close to each other - for (bucketIndex = 0; bucketIndex < kBuckets; ++bucketIndex) { + for (bucketIndex = 1; bucketIndex < kBuckets; ++bucketIndex) { // Move bucket memmove(mRecordArray + bucketIndex * newRecordsPerBucket, mRecordArray + bucketIndex * oldRecordsPerBucket, - mHeader.mBucketUsage[bucketIndex] * sizeof(nsDiskCacheRecord)); + newRecordsPerBucket * sizeof(nsDiskCacheRecord)); } // Shrink the record array memory block itself From b89baff607307d102a69cec0ed8b12c1cc33156b Mon Sep 17 00:00:00 2001 From: Cameron McCormack <cam@mcc.id.au> Date: Wed, 8 Aug 2012 21:37:11 +1000 Subject: [PATCH 150/169] Bug 655877 - Part 19: Add function to convert text decorations to a path. r=roc --- layout/base/nsCSSRendering.cpp | 47 ++++++++++++++++++++++++++++++++++ layout/base/nsCSSRendering.h | 20 +++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp index 1a5890461085..5738811517c1 100644 --- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -3554,6 +3554,53 @@ nsCSSRendering::PaintDecorationLine(nsIFrame* aFrame, } } +void +nsCSSRendering::DecorationLineToPath(nsIFrame* aFrame, + gfxContext* aGfxContext, + const gfxRect& aDirtyRect, + const nscolor aColor, + const gfxPoint& aPt, + const gfxFloat aXInFrame, + const gfxSize& aLineSize, + const gfxFloat aAscent, + const gfxFloat aOffset, + const PRUint8 aDecoration, + const PRUint8 aStyle, + const gfxFloat aDescentLimit) +{ + NS_ASSERTION(aStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE, "aStyle is none"); + + aGfxContext->NewPath(); + + gfxRect rect = + GetTextDecorationRectInternal(aPt, aLineSize, aAscent, aOffset, + aDecoration, aStyle, aDescentLimit); + if (rect.IsEmpty() || !rect.Intersects(aDirtyRect)) { + return; + } + + if (aDecoration != NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE && + aDecoration != NS_STYLE_TEXT_DECORATION_LINE_OVERLINE && + aDecoration != NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH) { + NS_ERROR("Invalid decoration value!"); + return; + } + + if (aStyle != NS_STYLE_TEXT_DECORATION_STYLE_SOLID) { + // For the moment, we support only solid text decorations. + return; + } + + gfxFloat lineHeight = NS_MAX(NS_round(aLineSize.height), 1.0); + + // The y position should be set to the middle of the line. + rect.y += lineHeight / 2; + + aGfxContext->Rectangle + (gfxRect(gfxPoint(rect.TopLeft() - gfxPoint(0.0, lineHeight / 2)), + gfxSize(rect.Width(), lineHeight))); +} + nsRect nsCSSRendering::GetTextDecorationRect(nsPresContext* aPresContext, const gfxSize& aLineSize, diff --git a/layout/base/nsCSSRendering.h b/layout/base/nsCSSRendering.h index 9fe38fd03177..8366e9f163f4 100644 --- a/layout/base/nsCSSRendering.h +++ b/layout/base/nsCSSRendering.h @@ -434,6 +434,26 @@ struct nsCSSRendering { const PRUint8 aStyle, const gfxFloat aDescentLimit = -1.0); + /** + * Adds a path corresponding to the outline of the decoration line to + * the specified context. Arguments have the same meaning as for + * PaintDecorationLine. Currently this only works for solid + * decorations; for other decoration styles, an empty path is added + * to the context. + */ + static void DecorationLineToPath(nsIFrame* aFrame, + gfxContext* aGfxContext, + const gfxRect& aDirtyRect, + const nscolor aColor, + const gfxPoint& aPt, + const gfxFloat aXInFrame, + const gfxSize& aLineSize, + const gfxFloat aAscent, + const gfxFloat aOffset, + const PRUint8 aDecoration, + const PRUint8 aStyle, + const gfxFloat aDescentLimit = -1.0); + /** * Function for getting the decoration line rect for the text. * NOTE: aLineSize, aAscent and aOffset are non-rounded device pixels, From a273d9a029e788e2e62b8aaaa4221e98a3591957 Mon Sep 17 00:00:00 2001 From: Cameron McCormack <cam@mcc.id.au> Date: Wed, 8 Aug 2012 21:37:12 +1000 Subject: [PATCH 151/169] Bug 655877 - Part 25: Give gfxTextRuns the ability to invoke a callback after painting glyphs and partial ligatures. r=roc --- gfx/thebes/gfxFont.cpp | 66 +++++++++++++++++++++++++++--------------- gfx/thebes/gfxFont.h | 22 ++++++++++++-- 2 files changed, 63 insertions(+), 25 deletions(-) diff --git a/gfx/thebes/gfxFont.cpp b/gfx/thebes/gfxFont.cpp index 97cbd2a01d6d..641c75fe7588 100644 --- a/gfx/thebes/gfxFont.cpp +++ b/gfx/thebes/gfxFont.cpp @@ -4602,16 +4602,12 @@ void gfxTextRun::DrawPartialLigature(gfxFont *aFont, gfxContext *aCtx, PRUint32 aStart, PRUint32 aEnd, gfxPoint *aPt, - PropertyProvider *aProvider) + PropertyProvider *aProvider, + gfxTextRun::DrawCallbacks *aCallbacks) { if (aStart >= aEnd) return; - // Need to preserve the path, otherwise this can break canvas text-on-path; - // in general it seems like a good thing, as naive callers probably won't - // expect gfxTextRun::Draw to implicitly destroy the current path. - gfxContextPathAutoSaveRestore savePath(aCtx); - // Draw partial ligature. We hack this by clipping the ligature. LigatureData data = ComputeLigatureData(aStart, aEnd, aProvider); gfxRect clipExtents = aCtx->GetClipExtents(); @@ -4619,20 +4615,33 @@ gfxTextRun::DrawPartialLigature(gfxFont *aFont, gfxContext *aCtx, gfxFloat right = clipExtents.XMost()*mAppUnitsPerDevUnit; ClipPartialLigature(this, &left, &right, aPt->x, &data); - aCtx->Save(); - aCtx->NewPath(); - // use division here to ensure that when the rect is aligned on multiples - // of mAppUnitsPerDevUnit, we clip to true device unit boundaries. - // Also, make sure we snap the rectangle to device pixels. - aCtx->Rectangle(gfxRect(left/mAppUnitsPerDevUnit, - clipExtents.Y(), - (right - left)/mAppUnitsPerDevUnit, - clipExtents.Height()), true); - aCtx->Clip(); + { + // Need to preserve the path, otherwise this can break canvas text-on-path; + // in general it seems like a good thing, as naive callers probably won't + // expect gfxTextRun::Draw to implicitly destroy the current path. + gfxContextPathAutoSaveRestore savePath(aCtx); + + // use division here to ensure that when the rect is aligned on multiples + // of mAppUnitsPerDevUnit, we clip to true device unit boundaries. + // Also, make sure we snap the rectangle to device pixels. + aCtx->Save(); + aCtx->NewPath(); + aCtx->Rectangle(gfxRect(left / mAppUnitsPerDevUnit, + clipExtents.Y(), + (right - left) / mAppUnitsPerDevUnit, + clipExtents.Height()), true); + aCtx->Clip(); + } + gfxFloat direction = GetDirection(); gfxPoint pt(aPt->x - direction*data.mPartAdvance, aPt->y); - DrawGlyphs(aFont, aCtx, gfxFont::GLYPH_FILL, &pt, nullptr, data.mLigatureStart, - data.mLigatureEnd, aProvider, aStart, aEnd); + DrawGlyphs(aFont, aCtx, + aCallbacks ? gfxFont::GLYPH_PATH : gfxFont::GLYPH_FILL, &pt, + nullptr, data.mLigatureStart, data.mLigatureEnd, aProvider, + aStart, aEnd); + if (aCallbacks) { + aCallbacks->NotifyGlyphPathEmitted(); + } aCtx->Restore(); aPt->x += direction*data.mPartWidth; @@ -4708,10 +4717,12 @@ void gfxTextRun::Draw(gfxContext *aContext, gfxPoint aPt, gfxFont::DrawMode aDrawMode, PRUint32 aStart, PRUint32 aLength, PropertyProvider *aProvider, gfxFloat *aAdvanceWidth, - gfxPattern *aStrokePattern) + gfxPattern *aStrokePattern, + gfxTextRun::DrawCallbacks *aCallbacks) { NS_ASSERTION(aStart + aLength <= mCharacterCount, "Substring out of range"); NS_ASSERTION(aDrawMode <= gfxFont::GLYPH_PATH, "GLYPH_PATH cannot be used with GLYPH_FILL or GLYPH_STROKE"); + NS_ASSERTION(aDrawMode == gfxFont::GLYPH_PATH || !aCallbacks, "callback must not be specified unless using GLYPH_PATH"); gfxFloat direction = GetDirection(); @@ -4755,15 +4766,24 @@ gfxTextRun::Draw(gfxContext *aContext, gfxPoint aPt, gfxFont::DrawMode aDrawMode PRUint32 ligatureRunEnd = end; ShrinkToLigatureBoundaries(&ligatureRunStart, &ligatureRunEnd); - if (aDrawMode == gfxFont::GLYPH_FILL) { - DrawPartialLigature(font, aContext, start, ligatureRunStart, &pt, aProvider); + bool drawPartial = aDrawMode == gfxFont::GLYPH_FILL || + aDrawMode == gfxFont::GLYPH_PATH && aCallbacks; + + if (drawPartial) { + DrawPartialLigature(font, aContext, start, ligatureRunStart, &pt, + aProvider, aCallbacks); } DrawGlyphs(font, aContext, aDrawMode, &pt, aStrokePattern, ligatureRunStart, ligatureRunEnd, aProvider, ligatureRunStart, ligatureRunEnd); - if (aDrawMode == gfxFont::GLYPH_FILL) { - DrawPartialLigature(font, aContext, ligatureRunEnd, end, &pt, aProvider); + if (aCallbacks) { + aCallbacks->NotifyGlyphPathEmitted(); + } + + if (drawPartial) { + DrawPartialLigature(font, aContext, ligatureRunEnd, end, &pt, + aProvider, aCallbacks); } } diff --git a/gfx/thebes/gfxFont.h b/gfx/thebes/gfxFont.h index a6db090f3654..e5ff657331e3 100644 --- a/gfx/thebes/gfxFont.h +++ b/gfx/thebes/gfxFont.h @@ -2471,6 +2471,22 @@ public: PRUint32 mCurrentChar; }; + /** + * Callback for Draw() to use when drawing text with mode + * gfxFont::GLYPH_PATH. + */ + struct DrawCallbacks { + + /** + * Called when a path has been emitted to the gfxContext when + * painting a text run. This can be called up to three times: + * once for any partial ligature at the beginning of the text run, + * once for the main run of glyphs, and once for any partial ligature + * at the end of the text run. + */ + virtual void NotifyGlyphPathEmitted() = 0; + }; + /** * Draws a substring. Uses only GetSpacing from aBreakProvider. * The provided point is the baseline origin on the left of the string @@ -2496,7 +2512,8 @@ public: gfxFont::DrawMode aDrawMode, PRUint32 aStart, PRUint32 aLength, PropertyProvider *aProvider, - gfxFloat *aAdvanceWidth, gfxPattern *aStrokePattern); + gfxFloat *aAdvanceWidth, gfxPattern *aStrokePattern, + DrawCallbacks *aCallbacks = nullptr); /** * Computes the ReflowMetrics for a substring. @@ -2918,7 +2935,8 @@ private: PropertyProvider *aProvider); void DrawPartialLigature(gfxFont *aFont, gfxContext *aCtx, PRUint32 aStart, PRUint32 aEnd, gfxPoint *aPt, - PropertyProvider *aProvider); + PropertyProvider *aProvider, + DrawCallbacks *aCallbacks); // Advance aStart to the start of the nearest ligature; back up aEnd // to the nearest ligature end; may result in *aStart == *aEnd void ShrinkToLigatureBoundaries(PRUint32 *aStart, PRUint32 *aEnd); From a4823ad875282874ec94656762af0441d44da84a Mon Sep 17 00:00:00 2001 From: Cameron McCormack <cam@mcc.id.au> Date: Wed, 8 Aug 2012 21:37:12 +1000 Subject: [PATCH 152/169] Bug 655877 - Part 26: Give nsTextFrames the ability to invoke callbacks after painting different parts of the text. r=roc --- layout/generic/nsTextFrame.h | 103 +++++++++- layout/generic/nsTextFrameThebes.cpp | 271 +++++++++++++++++++-------- 2 files changed, 287 insertions(+), 87 deletions(-) diff --git a/layout/generic/nsTextFrame.h b/layout/generic/nsTextFrame.h index 3a352909e649..ad64cff3381b 100644 --- a/layout/generic/nsTextFrame.h +++ b/layout/generic/nsTextFrame.h @@ -274,10 +274,86 @@ public: PRUint32* aStartOffset, PRUint32* aMaxLength, nscoord* aSnappedLeftEdge, nscoord* aSnappedRightEdge); - // primary frame paint method called from nsDisplayText - // The private DrawText() is what applies the text to a graphics context + + /** + * Object with various callbacks for PaintText() to invoke for different parts + * of the frame's text rendering, when we're generating paths rather than + * painting. + * + * Callbacks are invoked in the following order: + * + * (NotifyBeforeSelectionBackground NotifySelectionBackgroundPathEmitted)? + * (NotifyBeforeDecorationLine NotifyDecorationLinePathEmitted)* + * NotifyBeforeText + * NotifyGlyphPathEmitted* + * NotifyAfterText + * (NotifyBeforeDecorationLine NotifyDecorationLinePathEmitted)* + * (NotifyBeforeSelectionDecorationLine NotifySelectionDecorationLinePathEmitted)* + * + * The color of each part of the frame's text rendering is passed as an argument + * to the NotifyBefore* callback for that part. The nscolor can take on one of + * the three selection special colors defined in LookAndFeel.h -- + * NS_TRANSPARENT, NS_SAME_AS_FOREGROUND_COLOR and + * NS_40PERCENT_FOREGROUND_COLOR. + */ + struct DrawPathCallbacks : gfxTextRun::DrawCallbacks + { + /** + * Called just before any paths have been emitted to the gfxContext + * for the glyphs of the frame's text. + */ + virtual void NotifyBeforeText(nscolor aColor) { } + + /** + * Called just after all the paths have been emitted to the gfxContext + * for the glyphs of the frame's text. + */ + virtual void NotifyAfterText() { } + + /** + * Called just before a path corresponding to the selection background + * has been emitted to the gfxContext. + */ + virtual void NotifyBeforeSelectionBackground(nscolor aColor) { } + + /** + * Called just after a path corresponding to the selection background + * has been emitted to the gfxContext. + */ + virtual void NotifySelectionBackgroundPathEmitted() { } + + /** + * Called just before a path corresponding to a text decoration line + * has been emitted to the gfxContext. + */ + virtual void NotifyBeforeDecorationLine(nscolor aColor) { } + + /** + * Called just after a path corresponding to a text decoration line + * has been emitted to the gfxContext. + */ + virtual void NotifyDecorationLinePathEmitted() { } + + /** + * Called just before a path corresponding to a selection decoration line + * has been emitted to the gfxContext. + */ + virtual void NotifyBeforeSelectionDecorationLine(nscolor aColor) { } + + /** + * Called just after a path corresponding to a selection decoration line + * has been emitted to the gfxContext. + */ + virtual void NotifySelectionDecorationLinePathEmitted() { } + }; + + // Primary frame paint method called from nsDisplayText. Can also be used + // to generate paths rather than paint the frame's text by passing a callback + // object. The private DrawText() is what applies the text to a graphics + // context. void PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt, - const nsRect& aDirtyRect, const nsCharClipDisplayItem& aItem); + const nsRect& aDirtyRect, const nsCharClipDisplayItem& aItem, + DrawPathCallbacks* aCallbacks = nullptr); // helper: paint text frame when we're impacted by at least one selection. // Return false if the text was not painted and we should continue with // the fast path. @@ -289,7 +365,8 @@ public: PRUint32 aContentOffset, PRUint32 aContentLength, nsTextPaintStyle& aTextPaintStyle, - const nsCharClipDisplayItem::ClipEdges& aClipEdges); + const nsCharClipDisplayItem::ClipEdges& aClipEdges, + DrawPathCallbacks* aCallbacks); // helper: paint text with foreground and background colors determined // by selection(s). Also computes a mask of all selection types applying to // our text, returned in aAllTypes. @@ -305,7 +382,8 @@ public: nsTextPaintStyle& aTextPaintStyle, SelectionDetails* aDetails, SelectionType* aAllTypes, - const nsCharClipDisplayItem::ClipEdges& aClipEdges); + const nsCharClipDisplayItem::ClipEdges& aClipEdges, + DrawPathCallbacks* aCallbacks); // helper: paint text decorations for text selected by aSelectionType void PaintTextSelectionDecorations(gfxContext* aCtx, const gfxPoint& aFramePt, @@ -316,7 +394,8 @@ public: PRUint32 aContentLength, nsTextPaintStyle& aTextPaintStyle, SelectionDetails* aDetails, - SelectionType aSelectionType); + SelectionType aSelectionType, + DrawPathCallbacks* aCallbacks); virtual nscolor GetCaretColorAt(PRInt32 aOffset); @@ -526,8 +605,10 @@ protected: PRUint32 aOffset, PRUint32 aLength, PropertyProvider& aProvider, + nscolor aTextColor, gfxFloat& aAdvanceWidth, - bool aDrawSoftHyphen); + bool aDrawSoftHyphen, + DrawPathCallbacks* aCallbacks); void DrawTextRunAndDecorations(gfxContext* const aCtx, const gfxRect& aDirtyRect, @@ -537,11 +618,13 @@ protected: PRUint32 aLength, PropertyProvider& aProvider, const nsTextPaintStyle& aTextStyle, + nscolor aTextColor, const nsCharClipDisplayItem::ClipEdges& aClipEdges, gfxFloat& aAdvanceWidth, bool aDrawSoftHyphen, const TextDecorations& aDecorations, - const nscolor* const aDecorationOverrideColor); + const nscolor* const aDecorationOverrideColor, + DrawPathCallbacks* aCallbacks); void DrawText(gfxContext* const aCtx, const gfxRect& aDirtyRect, @@ -551,10 +634,12 @@ protected: PRUint32 aLength, PropertyProvider& aProvider, const nsTextPaintStyle& aTextStyle, + nscolor aTextColor, const nsCharClipDisplayItem::ClipEdges& aClipEdges, gfxFloat& aAdvanceWidth, bool aDrawSoftHyphen, - const nscolor* const aDecorationOverrideColor = nullptr); + const nscolor* const aDecorationOverrideColor = nullptr, + DrawPathCallbacks* aCallbacks = nullptr); // Set non empty rect to aRect, it should be overflow rect or frame rect. // If the result rect is larger than the given rect, this returns true. diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp index 37aedc2697bc..087fee01167e 100644 --- a/layout/generic/nsTextFrameThebes.cpp +++ b/layout/generic/nsTextFrameThebes.cpp @@ -278,6 +278,12 @@ class nsTextPaintStyle { public: nsTextPaintStyle(nsTextFrame* aFrame); + void SetResolveColors(bool aResolveColors) { + NS_ASSERTION(mFrame->IsSVGText() || aResolveColors, + "must resolve colors is frame is not for SVG text"); + mResolveColors = aResolveColors; + } + nscolor GetTextColor(); /** * Compute the colors for normally-selected text. Returns false if @@ -342,6 +348,7 @@ protected: nsPresContext* mPresContext; bool mInitCommonColors; bool mInitSelectionColorsAndShadow; + bool mResolveColors; // Selection data @@ -356,11 +363,12 @@ protected: PRInt32 mSufficientContrast; nscolor mFrameBackgroundColor; - // selection colors and underline info, the colors are resolved colors, - // i.e., the foreground color and background color are swapped if it's needed. - // And also line color will be resolved from them. + // selection colors and underline info, the colors are resolved colors if + // mResolveColors is true (which is the default), i.e., the foreground color + // and background color are swapped if it's needed. And also line color will + // be resolved from them. struct nsSelectionStyle { - bool mInit; + bool mInit; nscolor mTextColor; nscolor mBGColor; nscolor mUnderlineColor; @@ -3401,6 +3409,7 @@ nsTextPaintStyle::nsTextPaintStyle(nsTextFrame* aFrame) mPresContext(aFrame->PresContext()), mInitCommonColors(false), mInitSelectionColorsAndShadow(false), + mResolveColors(true), mHasSelectionShadow(false) { for (PRUint32 i = 0; i < ArrayLength(mSelectionStyle); i++) @@ -3642,12 +3651,18 @@ nsTextPaintStyle::InitSelectionColorsAndShadow() mSelectionTextColor = LookAndFeel::GetColor(LookAndFeel::eColorID_TextSelectForeground); - // On MacOS X, we don't exchange text color and BG color. - if (mSelectionTextColor == NS_DONT_CHANGE_COLOR) { - nscolor frameColor = mFrame->GetVisitedDependentColor(eCSSProperty_color); - mSelectionTextColor = EnsureDifferentColors(frameColor, mSelectionBGColor); + if (mResolveColors) { + // On MacOS X, we don't exchange text color and BG color. + if (mSelectionTextColor == NS_DONT_CHANGE_COLOR) { + nscolor frameColor = mFrame->GetVisitedDependentColor(eCSSProperty_color); + mSelectionTextColor = EnsureDifferentColors(frameColor, mSelectionBGColor); + } else { + EnsureSufficientContrast(&mSelectionTextColor, &mSelectionBGColor); + } } else { - EnsureSufficientContrast(&mSelectionTextColor, &mSelectionBGColor); + if (mSelectionTextColor == NS_DONT_CHANGE_COLOR) { + mSelectionTextColor = NS_SAME_AS_FOREGROUND_COLOR; + } } return true; } @@ -3722,17 +3737,21 @@ nsTextPaintStyle::InitSelectionStyle(PRInt32 aIndex) NS_ASSERTION(backColor != NS_40PERCENT_FOREGROUND_COLOR, "backColor cannot be NS_40PERCENT_FOREGROUND_COLOR"); - foreColor = GetResolvedForeColor(foreColor, GetTextColor(), backColor); + if (mResolveColors) { + foreColor = GetResolvedForeColor(foreColor, GetTextColor(), backColor); - if (NS_GET_A(backColor) > 0) - EnsureSufficientContrast(&foreColor, &backColor); + if (NS_GET_A(backColor) > 0) + EnsureSufficientContrast(&foreColor, &backColor); + } nscolor lineColor; float relativeSize; PRUint8 lineStyle; GetSelectionUnderline(mPresContext, aIndex, &lineColor, &relativeSize, &lineStyle); - lineColor = GetResolvedForeColor(lineColor, foreColor, backColor); + + if (mResolveColors) + lineColor = GetResolvedForeColor(lineColor, foreColor, backColor); selectionStyle->mTextColor = foreColor; selectionStyle->mBGColor = backColor; @@ -4536,9 +4555,15 @@ nsTextFrame::GetSelectionDetails() } static void -FillClippedRect(gfxContext* aCtx, nsPresContext* aPresContext, - nscolor aColor, const gfxRect& aDirtyRect, const gfxRect& aRect) +PaintSelectionBackground(gfxContext* aCtx, nsPresContext* aPresContext, + nscolor aColor, const gfxRect& aDirtyRect, + const gfxRect& aRect, + nsTextFrame::DrawPathCallbacks* aCallbacks) { + if (aCallbacks) { + aCallbacks->NotifyBeforeSelectionBackground(aColor); + } + gfxRect r = aRect.Intersect(aDirtyRect); // For now, we need to put this in pixel coordinates PRInt32 app = aPresContext->AppUnitsPerDevPixel(); @@ -4546,8 +4571,13 @@ FillClippedRect(gfxContext* aCtx, nsPresContext* aPresContext, // pixel-snap aCtx->Rectangle(gfxRect(r.X() / app, r.Y() / app, r.Width() / app, r.Height() / app), true); - aCtx->SetColor(gfxRGBA(aColor)); - aCtx->Fill(); + + if (aCallbacks) { + aCallbacks->NotifySelectionBackgroundPathEmitted(); + } else { + aCtx->SetColor(gfxRGBA(aColor)); + aCtx->Fill(); + } } void @@ -4848,6 +4878,50 @@ ComputeSelectionUnderlineHeight(nsPresContext* aPresContext, } } +enum DecorationType { + eNormalDecoration, + eSelectionDecoration +}; + +static void +PaintDecorationLine(nsIFrame* aFrame, + gfxContext* const aCtx, + const gfxRect& aDirtyRect, + nscolor aColor, + const nscolor* aOverrideColor, + const gfxPoint& aPt, + gfxFloat aXInFrame, + const gfxSize& aLineSize, + gfxFloat aAscent, + gfxFloat aOffset, + PRUint8 aDecoration, + PRUint8 aStyle, + DecorationType aDecorationType, + nsTextFrame::DrawPathCallbacks* aCallbacks, + gfxFloat aDescentLimit = -1.0) +{ + nscolor lineColor = aOverrideColor ? *aOverrideColor : aColor; + if (aCallbacks) { + if (aDecorationType == eNormalDecoration) { + aCallbacks->NotifyBeforeDecorationLine(lineColor); + } else { + aCallbacks->NotifyBeforeSelectionDecorationLine(lineColor); + } + nsCSSRendering::DecorationLineToPath(aFrame, aCtx, aDirtyRect, lineColor, + aPt, aXInFrame, aLineSize, aAscent, aOffset, aDecoration, aStyle, + aDescentLimit); + if (aDecorationType == eNormalDecoration) { + aCallbacks->NotifyDecorationLinePathEmitted(); + } else { + aCallbacks->NotifySelectionDecorationLinePathEmitted(); + } + } else { + nsCSSRendering::PaintDecorationLine(aFrame, aCtx, aDirtyRect, lineColor, + aPt, aXInFrame, aLineSize, aAscent, aOffset, aDecoration, aStyle, + aDescentLimit); + } +} + /** * This, plus SelectionTypesWithDecorations, encapsulates all knowledge about * drawing text decoration for selections. @@ -4859,7 +4933,8 @@ static void DrawSelectionDecorations(gfxContext* aContext, nsTextPaintStyle& aTextPaintStyle, const nsTextRangeStyle &aRangeStyle, const gfxPoint& aPt, gfxFloat aXInFrame, gfxFloat aWidth, - gfxFloat aAscent, const gfxFont::Metrics& aFontMetrics) + gfxFloat aAscent, const gfxFont::Metrics& aFontMetrics, + nsTextFrame::DrawPathCallbacks* aCallbacks) { gfxPoint pt(aPt); gfxSize size(aWidth, @@ -4935,9 +5010,10 @@ static void DrawSelectionDecorations(gfxContext* aContext, return; } size.height *= relativeSize; - nsCSSRendering::PaintDecorationLine(aFrame, aContext, aDirtyRect, color, pt, + PaintDecorationLine(aFrame, aContext, aDirtyRect, color, nullptr, pt, pt.x - aPt.x + aXInFrame, size, aAscent, aFontMetrics.underlineOffset, - NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE, style, descentLimit); + NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE, style, eSelectionDecoration, + aCallbacks, descentLimit); } /** @@ -5177,7 +5253,7 @@ nsTextFrame::PaintOneShadow(PRUint32 aOffset, PRUint32 aLength, } aCtx->Save(); - aCtx->NewPath(); + aCtx->NewPath(); aCtx->SetColor(gfxRGBA(shadowColor)); // Draw the text onto our alpha-only surface to capture the alpha values. @@ -5188,7 +5264,7 @@ nsTextFrame::PaintOneShadow(PRUint32 aOffset, PRUint32 aLength, aDirtyRect.width, aDirtyRect.height); DrawText(shadowContext, dirtyRect, aFramePt + shadowOffset, aTextBaselinePt + shadowOffset, aOffset, aLength, *aProvider, - nsTextPaintStyle(this), aClipEdges, advanceWidth, + nsTextPaintStyle(this), shadowColor, aClipEdges, advanceWidth, (GetStateBits() & TEXT_HYPHEN_BREAK) != 0, decorationOverrideColor); contextBoxBlur.DoPaint(); @@ -5205,7 +5281,8 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx, PRUint32 aContentOffset, PRUint32 aContentLength, nsTextPaintStyle& aTextPaintStyle, SelectionDetails* aDetails, SelectionType* aAllTypes, - const nsCharClipDisplayItem::ClipEdges& aClipEdges) + const nsCharClipDisplayItem::ClipEdges& aClipEdges, + nsTextFrame::DrawPathCallbacks* aCallbacks) { // Figure out which selections control the colors to use for each character. AutoFallibleTArray<SelectionDetails*,BIG_TEXT_NODE_SIZE> prevailingSelectionsBuffer; @@ -5273,9 +5350,10 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx, mTextRun->GetAdvanceWidth(offset, length, &aProvider); if (NS_GET_A(background) > 0) { gfxFloat x = xOffset - (mTextRun->IsRightToLeft() ? advance : 0); - FillClippedRect(aCtx, aTextPaintStyle.PresContext(), - background, aDirtyRect, - gfxRect(aFramePt.x + x, aFramePt.y, advance, GetSize().height)); + PaintSelectionBackground(aCtx, aTextPaintStyle.PresContext(), + background, aDirtyRect, + gfxRect(aFramePt.x + x, aFramePt.y, advance, + GetSize().height), aCallbacks); } iterator.UpdateWithAdvance(advance); } @@ -5320,12 +5398,11 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx, } // Draw text segment - aCtx->SetColor(gfxRGBA(foreground)); gfxFloat advance; DrawText(aCtx, aDirtyRect, aFramePt, textBaselinePt, - offset, length, aProvider, aTextPaintStyle, aClipEdges, advance, - hyphenWidth > 0); + offset, length, aProvider, aTextPaintStyle, foreground, aClipEdges, + advance, hyphenWidth > 0, nullptr, aCallbacks); if (hyphenWidth) { advance += hyphenWidth; } @@ -5341,7 +5418,8 @@ nsTextFrame::PaintTextSelectionDecorations(gfxContext* aCtx, PropertyProvider& aProvider, PRUint32 aContentOffset, PRUint32 aContentLength, nsTextPaintStyle& aTextPaintStyle, SelectionDetails* aDetails, - SelectionType aSelectionType) + SelectionType aSelectionType, + nsTextFrame::DrawPathCallbacks* aCallbacks) { // Hide text decorations if we're currently hiding @font-face fallback text if (aProvider.GetFontGroup()->ShouldSkipDrawing()) @@ -5401,7 +5479,8 @@ nsTextFrame::PaintTextSelectionDecorations(gfxContext* aCtx, gfxFloat xInFrame = pt.x - (aFramePt.x / app); DrawSelectionDecorations(aCtx, dirtyRect, aSelectionType, this, aTextPaintStyle, selectedStyle, pt, xInFrame, - width, mAscent / app, decorationMetrics); + width, mAscent / app, decorationMetrics, + aCallbacks); } iterator.UpdateWithAdvance(advance); } @@ -5414,7 +5493,8 @@ nsTextFrame::PaintTextWithSelection(gfxContext* aCtx, PropertyProvider& aProvider, PRUint32 aContentOffset, PRUint32 aContentLength, nsTextPaintStyle& aTextPaintStyle, - const nsCharClipDisplayItem::ClipEdges& aClipEdges) + const nsCharClipDisplayItem::ClipEdges& aClipEdges, + nsTextFrame::DrawPathCallbacks* aCallbacks) { NS_ASSERTION(GetContent()->IsSelectionDescendant(), "wrong paint path"); @@ -5427,7 +5507,7 @@ nsTextFrame::PaintTextWithSelection(gfxContext* aCtx, if (!PaintTextWithSelectionColors(aCtx, aFramePt, aTextBaselinePt, aDirtyRect, aProvider, aContentOffset, aContentLength, aTextPaintStyle, details, &allTypes, - aClipEdges)) { + aClipEdges, aCallbacks)) { DestroySelectionDetails(details); return false; } @@ -5445,7 +5525,8 @@ nsTextFrame::PaintTextWithSelection(gfxContext* aCtx, // PaintTextSelectionDecorations will exit early). PaintTextSelectionDecorations(aCtx, aFramePt, aTextBaselinePt, aDirtyRect, aProvider, aContentOffset, aContentLength, - aTextPaintStyle, details, type); + aTextPaintStyle, details, type, + aCallbacks); } } @@ -5610,7 +5691,8 @@ nsTextFrame::MeasureCharClippedText(PropertyProvider& aProvider, void nsTextFrame::PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt, const nsRect& aDirtyRect, - const nsCharClipDisplayItem& aItem) + const nsCharClipDisplayItem& aItem, + nsTextFrame::DrawPathCallbacks* aCallbacks) { // Don't pass in aRenderingContext here, because we need a *reference* // context and aRenderingContext might have some transform in it @@ -5640,6 +5722,7 @@ nsTextFrame::PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt, nsCharClipDisplayItem::ClipEdges clipEdges(aItem, snappedLeftEdge, snappedRightEdge); nsTextPaintStyle textPaintStyle(this); + textPaintStyle.SetResolveColors(!aCallbacks); gfxRect dirtyRect(aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height); @@ -5651,34 +5734,59 @@ nsTextFrame::PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt, tmp.ConvertSkippedToOriginal(startOffset + maxLength) - contentOffset; if (PaintTextWithSelection(ctx, framePt, textBaselinePt, dirtyRect, provider, contentOffset, contentLength, - textPaintStyle, clipEdges)) { + textPaintStyle, clipEdges, aCallbacks)) { return; } } nscolor foregroundColor = textPaintStyle.GetTextColor(); - const nsStyleText* textStyle = GetStyleText(); - if (textStyle->mTextShadow) { - // Text shadow happens with the last value being painted at the back, - // ie. it is painted first. - gfxTextRun::Metrics shadowMetrics = - mTextRun->MeasureText(startOffset, maxLength, gfxFont::LOOSE_INK_EXTENTS, - nullptr, &provider); - for (PRUint32 i = textStyle->mTextShadow->Length(); i > 0; --i) { - PaintOneShadow(startOffset, maxLength, - textStyle->mTextShadow->ShadowAt(i - 1), &provider, - aDirtyRect, framePt, textBaselinePt, ctx, - foregroundColor, clipEdges, - snappedLeftEdge, shadowMetrics.mBoundingBox); + if (!aCallbacks) { + const nsStyleText* textStyle = GetStyleText(); + if (textStyle->mTextShadow) { + // Text shadow happens with the last value being painted at the back, + // ie. it is painted first. + gfxTextRun::Metrics shadowMetrics = + mTextRun->MeasureText(startOffset, maxLength, gfxFont::LOOSE_INK_EXTENTS, + nullptr, &provider); + for (PRUint32 i = textStyle->mTextShadow->Length(); i > 0; --i) { + PaintOneShadow(startOffset, maxLength, + textStyle->mTextShadow->ShadowAt(i - 1), &provider, + aDirtyRect, framePt, textBaselinePt, ctx, + foregroundColor, clipEdges, + snappedLeftEdge, shadowMetrics.mBoundingBox); + } } } - ctx->SetColor(gfxRGBA(foregroundColor)); - gfxFloat advanceWidth; DrawText(ctx, dirtyRect, framePt, textBaselinePt, startOffset, maxLength, provider, - textPaintStyle, clipEdges, advanceWidth, - (GetStateBits() & TEXT_HYPHEN_BREAK) != 0); + textPaintStyle, foregroundColor, clipEdges, advanceWidth, + (GetStateBits() & TEXT_HYPHEN_BREAK) != 0, + nullptr, aCallbacks); +} + +static void +DrawTextRun(gfxTextRun* aTextRun, + gfxContext* const aCtx, + const gfxPoint& aTextBaselinePt, + PRUint32 aOffset, PRUint32 aLength, + PropertyProvider* aProvider, + nscolor aTextColor, + gfxFloat* aAdvanceWidth, + nsTextFrame::DrawPathCallbacks* aCallbacks) +{ + gfxFont::DrawMode drawMode = aCallbacks ? gfxFont::GLYPH_PATH : + gfxFont::GLYPH_FILL; + if (aCallbacks) { + aCallbacks->NotifyBeforeText(aTextColor); + aTextRun->Draw(aCtx, aTextBaselinePt, drawMode, aOffset, aLength, + aProvider, aAdvanceWidth, nullptr, aCallbacks); + aCallbacks->NotifyAfterText(); + } else { + aCtx->SetColor(gfxRGBA(aTextColor)); + aTextRun->Draw(aCtx, aTextBaselinePt, drawMode, aOffset, aLength, + aProvider, aAdvanceWidth, nullptr); + } } void @@ -5686,11 +5794,13 @@ nsTextFrame::DrawTextRun(gfxContext* const aCtx, const gfxPoint& aTextBaselinePt, PRUint32 aOffset, PRUint32 aLength, PropertyProvider& aProvider, + nscolor aTextColor, gfxFloat& aAdvanceWidth, - bool aDrawSoftHyphen) + bool aDrawSoftHyphen, + nsTextFrame::DrawPathCallbacks* aCallbacks) { - mTextRun->Draw(aCtx, aTextBaselinePt, gfxFont::GLYPH_FILL, aOffset, aLength, - &aProvider, &aAdvanceWidth, nullptr); + ::DrawTextRun(mTextRun, aCtx, aTextBaselinePt, aOffset, aLength, &aProvider, + aTextColor, &aAdvanceWidth, aCallbacks); if (aDrawSoftHyphen) { // Don't use ctx as the context, because we need a reference context here, @@ -5701,9 +5811,10 @@ nsTextFrame::DrawTextRun(gfxContext* const aCtx, // of the text, minus its own width gfxFloat hyphenBaselineX = aTextBaselinePt.x + mTextRun->GetDirection() * aAdvanceWidth - (mTextRun->IsRightToLeft() ? hyphenTextRun->GetAdvanceWidth(0, hyphenTextRun->GetLength(), nullptr) : 0); - hyphenTextRun->Draw(aCtx, gfxPoint(hyphenBaselineX, aTextBaselinePt.y), - gfxFont::GLYPH_FILL, 0, hyphenTextRun->GetLength(), - nullptr, nullptr, nullptr); + ::DrawTextRun(hyphenTextRun.get(), aCtx, + gfxPoint(hyphenBaselineX, aTextBaselinePt.y), + 0, hyphenTextRun->GetLength(), + nullptr, aTextColor, nullptr, aCallbacks); } } } @@ -5715,11 +5826,13 @@ nsTextFrame::DrawTextRunAndDecorations( PRUint32 aOffset, PRUint32 aLength, PropertyProvider& aProvider, const nsTextPaintStyle& aTextStyle, + nscolor aTextColor, const nsCharClipDisplayItem::ClipEdges& aClipEdges, gfxFloat& aAdvanceWidth, bool aDrawSoftHyphen, const TextDecorations& aDecorations, - const nscolor* const aDecorationOverrideColor) + const nscolor* const aDecorationOverrideColor, + nsTextFrame::DrawPathCallbacks* aCallbacks) { const gfxFloat app = aTextStyle.PresContext()->AppUnitsPerDevPixel(); @@ -5751,10 +5864,10 @@ nsTextFrame::DrawTextRunAndDecorations( decSize.height = metrics.underlineSize; decPt.y = (frameTop - dec.mBaselineOffset) / app; - const nscolor lineColor = aDecorationOverrideColor ? *aDecorationOverrideColor : dec.mColor; - nsCSSRendering::PaintDecorationLine(this, aCtx, dirtyRect, lineColor, - decPt, 0.0, decSize, ascent, metrics.underlineOffset, - NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE, dec.mStyle); + PaintDecorationLine(this, aCtx, dirtyRect, dec.mColor, + aDecorationOverrideColor, decPt, 0.0, decSize, ascent, + metrics.underlineOffset, NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE, + dec.mStyle, eNormalDecoration, aCallbacks); } // Overlines for (PRUint32 i = aDecorations.mOverlines.Length(); i-- > 0; ) { @@ -5768,16 +5881,16 @@ nsTextFrame::DrawTextRunAndDecorations( decSize.height = metrics.underlineSize; decPt.y = (frameTop - dec.mBaselineOffset) / app; - const nscolor lineColor = aDecorationOverrideColor ? *aDecorationOverrideColor : dec.mColor; - nsCSSRendering::PaintDecorationLine(this, aCtx, dirtyRect, lineColor, - decPt, 0.0, decSize, ascent, metrics.maxAscent, - NS_STYLE_TEXT_DECORATION_LINE_OVERLINE, dec.mStyle); + PaintDecorationLine(this, aCtx, dirtyRect, dec.mColor, + aDecorationOverrideColor, decPt, 0.0, decSize, ascent, + metrics.maxAscent, NS_STYLE_TEXT_DECORATION_LINE_OVERLINE, dec.mStyle, + eNormalDecoration, aCallbacks); } // CSS 2.1 mandates that text be painted after over/underlines, and *then* // line-throughs - DrawTextRun(aCtx, aTextBaselinePt, aOffset, aLength, aProvider, aAdvanceWidth, - aDrawSoftHyphen); + DrawTextRun(aCtx, aTextBaselinePt, aOffset, aLength, aProvider, aTextColor, + aAdvanceWidth, aDrawSoftHyphen, aCallbacks); // Line-throughs for (PRUint32 i = aDecorations.mStrikes.Length(); i-- > 0; ) { @@ -5791,10 +5904,10 @@ nsTextFrame::DrawTextRunAndDecorations( decSize.height = metrics.strikeoutSize; decPt.y = (frameTop - dec.mBaselineOffset) / app; - const nscolor lineColor = aDecorationOverrideColor ? *aDecorationOverrideColor : dec.mColor; - nsCSSRendering::PaintDecorationLine(this, aCtx, dirtyRect, lineColor, - decPt, 0.0, decSize, ascent, metrics.strikeoutOffset, - NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH, dec.mStyle); + PaintDecorationLine(this, aCtx, dirtyRect, dec.mColor, + aDecorationOverrideColor, decPt, 0.0, decSize, ascent, + metrics.strikeoutOffset, NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH, + dec.mStyle, eNormalDecoration, aCallbacks); } } @@ -5805,10 +5918,12 @@ nsTextFrame::DrawText( PRUint32 aOffset, PRUint32 aLength, PropertyProvider& aProvider, const nsTextPaintStyle& aTextStyle, + nscolor aTextColor, const nsCharClipDisplayItem::ClipEdges& aClipEdges, gfxFloat& aAdvanceWidth, bool aDrawSoftHyphen, - const nscolor* const aDecorationOverrideColor) + const nscolor* const aDecorationOverrideColor, + nsTextFrame::DrawPathCallbacks* aCallbacks) { TextDecorations decorations; GetTextDecorations(aTextStyle.PresContext(), decorations); @@ -5818,12 +5933,12 @@ nsTextFrame::DrawText( decorations.HasDecorationLines(); if (drawDecorations) { DrawTextRunAndDecorations(aCtx, aDirtyRect, aFramePt, aTextBaselinePt, aOffset, aLength, - aProvider, aTextStyle, aClipEdges, aAdvanceWidth, + aProvider, aTextStyle, aTextColor, aClipEdges, aAdvanceWidth, aDrawSoftHyphen, decorations, - aDecorationOverrideColor); + aDecorationOverrideColor, aCallbacks); } else { DrawTextRun(aCtx, aTextBaselinePt, aOffset, aLength, aProvider, - aAdvanceWidth, aDrawSoftHyphen); + aTextColor, aAdvanceWidth, aDrawSoftHyphen, aCallbacks); } } From 444f2c079a6982daaf1c29c411a2c662e960f051 Mon Sep 17 00:00:00 2001 From: Cameron McCormack <cam@mcc.id.au> Date: Wed, 8 Aug 2012 21:37:13 +1000 Subject: [PATCH 153/169] Bug 655877 - Part 27: Ignore text-shadow in SVG text frames. r=roc --- layout/base/nsLayoutUtils.cpp | 5 +++-- layout/generic/nsTextFrameThebes.cpp | 12 ++++++++---- layout/style/nsStyleStruct.h | 4 ++++ layout/style/nsStyleStructInlines.h | 15 +++++++++++++++ 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 81b2f6d39def..7de020adc195 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -76,6 +76,7 @@ #include "nsSVGIntegrationUtils.h" #include "nsSVGForeignObjectFrame.h" #include "nsSVGOuterSVGFrame.h" +#include "nsStyleStructInlines.h" #include "mozilla/Preferences.h" @@ -2118,7 +2119,7 @@ nsLayoutUtils::GetTextShadowRectsUnion(const nsRect& aTextAndDecorationsRect, PRUint32 aFlags) { const nsStyleText* textStyle = aFrame->GetStyleText(); - if (!textStyle->mTextShadow) + if (!textStyle->HasTextShadow(aFrame)) return aTextAndDecorationsRect; nsRect resultRect = aTextAndDecorationsRect; @@ -3224,7 +3225,7 @@ nsLayoutUtils::PaintTextShadow(const nsIFrame* aFrame, void* aCallbackData) { const nsStyleText* textStyle = aFrame->GetStyleText(); - if (!textStyle->mTextShadow) + if (!textStyle->HasTextShadow(aFrame)) return; // Text shadow happens with the last value being painted at the back, diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp index 087fee01167e..f8ddbeb955c7 100644 --- a/layout/generic/nsTextFrameThebes.cpp +++ b/layout/generic/nsTextFrameThebes.cpp @@ -5075,10 +5075,14 @@ static bool GetSelectionTextColors(SelectionType aType, * If text-shadow was not specified, *aShadow is left untouched * (NOT reset to null), and the function returns false. */ -static bool GetSelectionTextShadow(SelectionType aType, +static bool GetSelectionTextShadow(nsIFrame* aFrame, + SelectionType aType, nsTextPaintStyle& aTextPaintStyle, nsCSSShadowArray** aShadow) { + if (aFrame->IsSVGText()) { + return false; + } switch (aType) { case nsISelectionController::SELECTION_NORMAL: return aTextPaintStyle.GetSelectionShadow(aShadow); @@ -5374,8 +5378,8 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx, // Determine what shadow, if any, to draw - either from textStyle // or from the ::-moz-selection pseudo-class if specified there - nsCSSShadowArray *shadow = textStyle->mTextShadow; - GetSelectionTextShadow(type, aTextPaintStyle, &shadow); + nsCSSShadowArray *shadow = textStyle->GetTextShadow(this); + GetSelectionTextShadow(this, type, aTextPaintStyle, &shadow); // Draw shadows, if any if (shadow) { @@ -5742,7 +5746,7 @@ nsTextFrame::PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt, nscolor foregroundColor = textPaintStyle.GetTextColor(); if (!aCallbacks) { const nsStyleText* textStyle = GetStyleText(); - if (textStyle->mTextShadow) { + if (textStyle->HasTextShadow(this)) { // Text shadow happens with the last value being painted at the back, // ie. it is painted first. gfxTextRun::Metrics shadowMetrics = diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index 7e62049e1d53..09779a72451b 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -1324,6 +1324,10 @@ struct nsStyleText { bool WordCanWrap() const { return WhiteSpaceCanWrap() && mWordWrap == NS_STYLE_WORDWRAP_BREAK_WORD; } + + // These are defined in nsStyleStructInlines.h. + inline bool HasTextShadow(const nsIFrame* aFrame) const; + inline nsCSSShadowArray* GetTextShadow(const nsIFrame* aFrame) const; }; struct nsStyleVisibility { diff --git a/layout/style/nsStyleStructInlines.h b/layout/style/nsStyleStructInlines.h index fa33a73f0858..59bf8382dbd3 100644 --- a/layout/style/nsStyleStructInlines.h +++ b/layout/style/nsStyleStructInlines.h @@ -55,6 +55,21 @@ nsStyleBorder::GetSubImage(PRUint8 aIndex) const return subImage; } +bool +nsStyleText::HasTextShadow(const nsIFrame* aFrame) const +{ + return mTextShadow && !aFrame->IsSVGText(); +} + +nsCSSShadowArray* +nsStyleText::GetTextShadow(const nsIFrame* aFrame) const +{ + if (aFrame->IsSVGText()) { + return nullptr; + } + return mTextShadow; +} + bool nsStyleDisplay::IsBlockInside(const nsIFrame* aFrame) const { From e79a5f487d9426586a6080e40c738b2f736d9b8b Mon Sep 17 00:00:00 2001 From: Cameron McCormack <cam@mcc.id.au> Date: Wed, 8 Aug 2012 21:37:13 +1000 Subject: [PATCH 154/169] Bug 655877 - Part 28: Paint SVG text frames using 'fill' not 'color'. r=roc --- layout/generic/nsTextFrame.h | 5 +++ layout/generic/nsTextFrameThebes.cpp | 67 ++++++++++++++++++++++++---- 2 files changed, 64 insertions(+), 8 deletions(-) diff --git a/layout/generic/nsTextFrame.h b/layout/generic/nsTextFrame.h index ad64cff3381b..138553794166 100644 --- a/layout/generic/nsTextFrame.h +++ b/layout/generic/nsTextFrame.h @@ -597,7 +597,12 @@ protected: return !mStrikes.IsEmpty(); } }; + enum TextDecorationColorResolution { + eResolvedColors, + eUnresolvedColors + }; void GetTextDecorations(nsPresContext* aPresContext, + TextDecorationColorResolution aColorResolution, TextDecorations& aDecorations); void DrawTextRun(gfxContext* const aCtx, diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp index f8ddbeb955c7..885865f69871 100644 --- a/layout/generic/nsTextFrameThebes.cpp +++ b/layout/generic/nsTextFrameThebes.cpp @@ -3444,6 +3444,21 @@ nsTextPaintStyle::EnsureSufficientContrast(nscolor *aForeColor, nscolor *aBackCo nscolor nsTextPaintStyle::GetTextColor() { + if (mFrame->IsSVGText()) { + if (!mResolveColors) + return NS_SAME_AS_FOREGROUND_COLOR; + + const nsStyleSVG* style = mFrame->GetStyleSVG(); + switch (style->mFill.mType) { + case eStyleSVGPaintType_None: + return NS_RGBA(0, 0, 0, 0); + case eStyleSVGPaintType_Color: + return nsLayoutUtils::GetColor(mFrame, eCSSProperty_fill); + default: + NS_ERROR("cannot resolve SVG paint to nscolor"); + return NS_RGBA(0, 0, 0, 255); + } + } return nsLayoutUtils::GetColor(mFrame, eCSSProperty_color); } @@ -3654,7 +3669,9 @@ nsTextPaintStyle::InitSelectionColorsAndShadow() if (mResolveColors) { // On MacOS X, we don't exchange text color and BG color. if (mSelectionTextColor == NS_DONT_CHANGE_COLOR) { - nscolor frameColor = mFrame->GetVisitedDependentColor(eCSSProperty_color); + nsCSSProperty property = mFrame->IsSVGText() ? eCSSProperty_fill : + eCSSProperty_color; + nscoord frameColor = mFrame->GetVisitedDependentColor(property); mSelectionTextColor = EnsureDifferentColors(frameColor, mSelectionBGColor); } else { EnsureSufficientContrast(&mSelectionTextColor, &mSelectionBGColor); @@ -4581,8 +4598,10 @@ PaintSelectionBackground(gfxContext* aCtx, nsPresContext* aPresContext, } void -nsTextFrame::GetTextDecorations(nsPresContext* aPresContext, - nsTextFrame::TextDecorations& aDecorations) +nsTextFrame::GetTextDecorations( + nsPresContext* aPresContext, + nsTextFrame::TextDecorationColorResolution aColorResolution, + nsTextFrame::TextDecorations& aDecorations) { const nsCompatibility compatMode = aPresContext->CompatibilityMode(); @@ -4651,8 +4670,23 @@ nsTextFrame::GetTextDecorations(nsPresContext* aPresContext, const PRUint8 style = styleText->GetDecorationStyle(); // Accumulate only elements that have decorations with a genuine style if (textDecorations && style != NS_STYLE_TEXT_DECORATION_STYLE_NONE) { - const nscolor color = useOverride ? overrideColor - : nsLayoutUtils::GetColor(f, eCSSProperty_text_decoration_color); + nscolor color; + if (useOverride) { + color = overrideColor; + } else if (IsSVGText()) { + // XXX We might want to do something with text-decoration-color when + // painting SVG text, but it's not clear what we should do. We + // at least need SVG text decorations to paint with 'fill' if + // text-decoration-color has its initial value currentColor. + // We could choose to interpret currentColor as "currentFill" + // for SVG text, and have e.g. text-decoration-color:red to + // override the fill paint of the decoration. + color = aColorResolution == eResolvedColors ? + nsLayoutUtils::GetColor(f, eCSSProperty_fill) : + NS_SAME_AS_FOREGROUND_COLOR; + } else { + color = nsLayoutUtils::GetColor(f, eCSSProperty_text_decoration_color); + } if (textDecorations & NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE) { aDecorations.mUnderlines.AppendElement( @@ -4744,7 +4778,7 @@ nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext, // maxima and minima are required to reliably generate the rectangle for // them TextDecorations textDecs; - GetTextDecorations(aPresContext, textDecs); + GetTextDecorations(aPresContext, eResolvedColors, textDecs); if (textDecs.HasDecorationLines()) { nscoord inflationMinFontSize = nsLayoutUtils::InflationMinFontSizeFor(aBlockReflowState.frame); @@ -5556,7 +5590,17 @@ nsTextFrame::GetCaretColorAt(PRInt32 aOffset) return result; } + bool isSolidTextColor = true; + if (IsSVGText()) { + const nsStyleSVG* style = GetStyleSVG(); + if (style->mFill.mType != eStyleSVGPaintType_None && + style->mFill.mType != eStyleSVGPaintType_Color) { + isSolidTextColor = false; + } + } + nsTextPaintStyle textPaintStyle(this); + textPaintStyle.SetResolveColors(isSolidTextColor); SelectionDetails* details = GetSelectionDetails(); SelectionDetails* sdptr = details; SelectionType type = 0; @@ -5569,7 +5613,12 @@ nsTextFrame::GetCaretColorAt(PRInt32 aOffset) if (GetSelectionTextColors(sdptr->mType, textPaintStyle, sdptr->mTextRangeStyle, &foreground, &background)) { - result = foreground; + if (!isSolidTextColor && + NS_IS_SELECTION_SPECIAL_COLOR(foreground)) { + result = NS_RGBA(0, 0, 0, 255); + } else { + result = foreground; + } type = sdptr->mType; } } @@ -5930,7 +5979,9 @@ nsTextFrame::DrawText( nsTextFrame::DrawPathCallbacks* aCallbacks) { TextDecorations decorations; - GetTextDecorations(aTextStyle.PresContext(), decorations); + GetTextDecorations(aTextStyle.PresContext(), + aCallbacks ? eUnresolvedColors : eResolvedColors, + decorations); // Hide text decorations if we're currently hiding @font-face fallback text const bool drawDecorations = !aProvider.GetFontGroup()->ShouldSkipDrawing() && From 37e33d3ddd4b694c6b145b6f817e23a3e87f2b08 Mon Sep 17 00:00:00 2001 From: Cameron McCormack <cam@mcc.id.au> Date: Wed, 8 Aug 2012 21:37:13 +1000 Subject: [PATCH 155/169] Bug 655877 - Part 31a: Atom for new frame class nsSVGTextFrame2. r=roc --- content/base/src/nsGkAtomList.h | 1 + 1 file changed, 1 insertion(+) diff --git a/content/base/src/nsGkAtomList.h b/content/base/src/nsGkAtomList.h index 0b4613cfa803..2049e2847306 100644 --- a/content/base/src/nsGkAtomList.h +++ b/content/base/src/nsGkAtomList.h @@ -1759,6 +1759,7 @@ GK_ATOM(svgRadialGradientFrame, "SVGRadialGradientFrame") GK_ATOM(svgStopFrame, "SVGStopFrame") GK_ATOM(svgSwitchFrame, "SVGSwitchFrame") GK_ATOM(svgTextFrame, "SVGTextFrame") +GK_ATOM(svgTextFrame2, "SVGTextFrame2") GK_ATOM(svgTextPathFrame, "SVGTextPathFrame") GK_ATOM(svgTSpanFrame, "SVGTSpanFrame") GK_ATOM(svgUseFrame, "SVGUseFrame") From de6e2e472d3295f5e21ae492a6717f19a735a7bc Mon Sep 17 00:00:00 2001 From: Cameron McCormack <cam@mcc.id.au> Date: Wed, 8 Aug 2012 21:37:14 +1000 Subject: [PATCH 156/169] Bug 655877 - Part 32: Allow nsCharClipDisplayItems to be constructed without an nsDisplayListBuilder. r=roc --- layout/base/nsDisplayList.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index c213eaf89793..df3471911737 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -2428,6 +2428,9 @@ public: nsCharClipDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) : nsDisplayItem(aBuilder, aFrame), mLeftEdge(0), mRightEdge(0) {} + nsCharClipDisplayItem(nsIFrame* aFrame) + : nsDisplayItem(nsnull, aFrame, nsPoint()) {} + struct ClipEdges { ClipEdges(const nsDisplayItem& aItem, nscoord aLeftEdge, nscoord aRightEdge) { From a837430ab24e486b350aa6df7794ec2a9e9f386f Mon Sep 17 00:00:00 2001 From: Cameron McCormack <cam@mcc.id.au> Date: Wed, 8 Aug 2012 21:37:14 +1000 Subject: [PATCH 157/169] Bug 655877 - Part 40: Factor out 'distance from point to rect' calculation from text frame selection routine. r=roc --- layout/base/nsLayoutUtils.h | 59 +++++++++++++++++++++++++++++++++++++ layout/generic/nsFrame.cpp | 37 +++-------------------- 2 files changed, 63 insertions(+), 33 deletions(-) diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 76caa1cd0320..f22aa10412be 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -40,6 +40,8 @@ class nsHTMLImageElement; #include "nsIFrameLoader.h" #include "FrameMetrics.h" +#include <limits> + class nsBlockFrame; class gfxDrawable; @@ -1676,6 +1678,22 @@ public: nsRestyleHint aRestyleHint, nsChangeHint aMinChangeHint); + /** + * Updates a pair of x and y distances if a given point is closer to a given + * rectangle than the original distance values. If aPoint is closer to + * aRect than aClosestXDistance and aClosestYDistance indicate, then those + * two variables are updated with the distance between aPoint and aRect, + * and true is returned. If aPoint is not closer, then aClosestXDistance + * and aClosestYDistance are left unchanged, and false is returned. + * + * Distances are measured in the two dimensions separately; a closer x + * distance beats a closer y distance. + */ + template<typename PointType, typename RectType, typename CoordType> + static bool PointIsCloserToRect(PointType aPoint, const RectType& aRect, + CoordType& aClosestXDistance, + CoordType& aClosestYDistance); + #ifdef DEBUG /** * Assert that there are no duplicate continuations of the same frame @@ -1700,6 +1718,47 @@ private: static PRUint32 sFontSizeInflationLineThreshold; }; +template<typename PointType, typename RectType, typename CoordType> +/* static */ bool +nsLayoutUtils::PointIsCloserToRect(PointType aPoint, const RectType& aRect, + CoordType& aClosestXDistance, + CoordType& aClosestYDistance) +{ + CoordType fromLeft = aPoint.x - aRect.x; + CoordType fromRight = aPoint.x - aRect.XMost(); + + CoordType xDistance; + if (fromLeft >= 0 && fromRight <= 0) { + xDistance = 0; + } else { + xDistance = NS_MIN(abs(fromLeft), abs(fromRight)); + } + + if (xDistance <= aClosestXDistance) { + if (xDistance < aClosestXDistance) { + aClosestYDistance = std::numeric_limits<CoordType>::max(); + } + + CoordType fromTop = aPoint.y - aRect.y; + CoordType fromBottom = aPoint.y - aRect.YMost(); + + CoordType yDistance; + if (fromTop >= 0 && fromBottom <= 0) { + yDistance = 0; + } else { + yDistance = NS_MIN(abs(fromTop), abs(fromBottom)); + } + + if (yDistance < aClosestYDistance) { + aClosestXDistance = xDistance; + aClosestYDistance = yDistance; + return true; + } + } + + return false; +} + namespace mozilla { namespace layout { diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 04718f42b5b0..dc4c9de3647b 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -3416,39 +3416,10 @@ static FrameTarget GetSelectionClosestFrame(nsIFrame* aFrame, nsPoint aPoint, if (!SelfIsSelectable(kid, aFlags) || kid->IsEmpty()) continue; - nsRect rect = kid->GetRect(); - - nscoord fromLeft = aPoint.x - rect.x; - nscoord fromRight = aPoint.x - rect.XMost(); - - nscoord xDistance; - if (fromLeft >= 0 && fromRight <= 0) { - xDistance = 0; - } else { - xDistance = NS_MIN(abs(fromLeft), abs(fromRight)); - } - - if (xDistance <= closestXDistance) - { - if (xDistance < closestXDistance) - closestYDistance = HUGE_DISTANCE; - - nscoord fromTop = aPoint.y - rect.y; - nscoord fromBottom = aPoint.y - rect.YMost(); - - nscoord yDistance; - if (fromTop >= 0 && fromBottom <= 0) - yDistance = 0; - else - yDistance = NS_MIN(abs(fromTop), abs(fromBottom)); - - if (yDistance < closestYDistance) - { - closestXDistance = xDistance; - closestYDistance = yDistance; - closestFrame = kid; - } - } + if (nsLayoutUtils::PointIsCloserToRect(aPoint, kid->GetRect(), + closestXDistance, + closestYDistance)) + closestFrame = kid; } if (closestFrame) return GetSelectionClosestFrameForChild(closestFrame, aPoint, aFlags); From a405b6dde8df277d97cbfb3baaec176b5bdea8ed Mon Sep 17 00:00:00 2001 From: Chris Lord <chrislord.net@gmail.com> Date: Wed, 8 Aug 2012 12:46:55 +0100 Subject: [PATCH 158/169] Bug 775431 - Add missing indentation for MOZ_DUMP_PAINT_LIST. r=mattwoodrow This part of the patch got lost rebasing somewhere. --- layout/base/nsLayoutDebugger.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/layout/base/nsLayoutDebugger.cpp b/layout/base/nsLayoutDebugger.cpp index e41a74ffaae7..063d0b4283a0 100644 --- a/layout/base/nsLayoutDebugger.cpp +++ b/layout/base/nsLayoutDebugger.cpp @@ -138,6 +138,9 @@ PrintDisplayListTo(nsDisplayListBuilder* aBuilder, const nsDisplayList& aList, fprintf(aOutput, "<li>"); } else { sPrintDisplayListIndent ++; + for (int indent = 0; indent < sPrintDisplayListIndent; indent++) { + fprintf(aOutput, " "); + } } nsIFrame* f = i->GetUnderlyingFrame(); nsAutoString fName; From 3d2ce33f14ca07d7e461c2d31055e32016c3ce62 Mon Sep 17 00:00:00 2001 From: Cameron McCormack <cam@mcc.id.au> Date: Wed, 8 Aug 2012 21:46:06 +1000 Subject: [PATCH 159/169] Bug 655877 - Part 22: Add function for getting the 'is SVG text using CSS frames' pref. r=jwatt --HG-- extra : rebase_source : 781039f078c347146299e66eef57b515fdc843a0 --- layout/svg/base/src/nsSVGUtils.cpp | 10 ++++++++++ layout/svg/base/src/nsSVGUtils.h | 1 + 2 files changed, 11 insertions(+) diff --git a/layout/svg/base/src/nsSVGUtils.cpp b/layout/svg/base/src/nsSVGUtils.cpp index 81605c72d89a..7e57a2c379e2 100644 --- a/layout/svg/base/src/nsSVGUtils.cpp +++ b/layout/svg/base/src/nsSVGUtils.cpp @@ -137,6 +137,7 @@ static const PRUint8 gsRGBToLinearRGBMap[256] = { static bool sSMILEnabled; static bool sSVGDisplayListHitTestingEnabled; static bool sSVGDisplayListPaintingEnabled; +static bool sSVGTextCSSFramesEnabled; bool NS_SMILEnabled() @@ -156,6 +157,12 @@ NS_SVGDisplayListPaintingEnabled() return sSVGDisplayListPaintingEnabled; } +bool +NS_SVGTextCSSFramesEnabled() +{ + return sSVGTextCSSFramesEnabled; +} + // we only take the address of this: static mozilla::gfx::UserDataKey sSVGAutoRenderStateKey; @@ -218,6 +225,9 @@ nsSVGUtils::Init() Preferences::AddBoolVarCache(&sSVGDisplayListPaintingEnabled, "svg.display-lists.painting.enabled"); + + Preferences::AddBoolVarCache(&sSVGTextCSSFramesEnabled, + "svg.text.css-frames.enabled"); } nsSVGSVGElement* diff --git a/layout/svg/base/src/nsSVGUtils.h b/layout/svg/base/src/nsSVGUtils.h index aeee5abe03fb..142c338ff4c9 100644 --- a/layout/svg/base/src/nsSVGUtils.h +++ b/layout/svg/base/src/nsSVGUtils.h @@ -112,6 +112,7 @@ bool NS_SMILEnabled(); bool NS_SVGDisplayListHitTestingEnabled(); bool NS_SVGDisplayListPaintingEnabled(); +bool NS_SVGTextCSSFramesEnabled(); /** * Sometimes we need to distinguish between an empty box and a box From 2c3082317dd146a33309622a29dab3a0f492b71d Mon Sep 17 00:00:00 2001 From: Ed Morley <emorley@mozilla.com> Date: Wed, 8 Aug 2012 13:11:34 +0100 Subject: [PATCH 160/169] Backout ec46cfa51bf8, 4a54f06efee8, de811fbd27b0 & 67ea1314c777 (bug 567077) for causing bug 781141 --- .../html/content/public/nsHTMLMediaElement.h | 12 -- .../html/content/src/nsHTMLMediaElement.cpp | 23 +--- content/media/MediaResource.cpp | 24 +--- content/media/test/Makefile.in | 7 +- content/media/test/contentType.sjs | 77 ------------- content/media/test/id3tags.mp3 | Bin 3530 -> 0 bytes content/media/test/manifest.js | 13 --- content/media/test/notags.mp3 | Bin 2506 -> 0 bytes content/media/test/short.mp4 | Bin 29435 -> 0 bytes content/media/test/test_media_sniffer.html | 70 ------------ netwerk/mime/nsMimeTypes.h | 1 - toolkit/components/Makefile.in | 1 - toolkit/components/mediasniffer/Makefile.in | 30 ----- .../mediasniffer/nsMediaSniffer.cpp | 107 ------------------ .../components/mediasniffer/nsMediaSniffer.h | 41 ------- .../mediasniffer/nsMediaSnifferModule.cpp | 37 ------ toolkit/library/Makefile.in | 1 - toolkit/library/nsStaticXULComponents.cpp | 1 - 18 files changed, 12 insertions(+), 433 deletions(-) delete mode 100644 content/media/test/contentType.sjs delete mode 100644 content/media/test/id3tags.mp3 delete mode 100644 content/media/test/notags.mp3 delete mode 100644 content/media/test/short.mp4 delete mode 100644 content/media/test/test_media_sniffer.html delete mode 100644 toolkit/components/mediasniffer/Makefile.in delete mode 100644 toolkit/components/mediasniffer/nsMediaSniffer.cpp delete mode 100644 toolkit/components/mediasniffer/nsMediaSniffer.h delete mode 100644 toolkit/components/mediasniffer/nsMediaSnifferModule.cpp diff --git a/content/html/content/public/nsHTMLMediaElement.h b/content/html/content/public/nsHTMLMediaElement.h index 264fc194235b..0f6c1f262395 100644 --- a/content/html/content/public/nsHTMLMediaElement.h +++ b/content/html/content/public/nsHTMLMediaElement.h @@ -312,11 +312,6 @@ public: static bool IsMediaPluginsType(const nsACString& aType); #endif - /** - * Get the mime type for this element. - */ - void GetMimeType(nsCString& aMimeType); - /** * Called when a child source element is added to this media element. This * may queue a task to run the select resource algorithm if appropriate. @@ -877,13 +872,6 @@ protected: // True if the media's channel's download has been suspended. bool mDownloadSuspendedByCache; - - // The Content-Type for this media. When we are sniffing for the Content-Type, - // and we are recreating a channel after the initial load, we need that - // information to give it as a hint to the channel for it to bypass the - // sniffing phase, that would fail because sniffing only works when applied to - // the first bytes of the stream. - nsCString mMimeType; }; #endif diff --git a/content/html/content/src/nsHTMLMediaElement.cpp b/content/html/content/src/nsHTMLMediaElement.cpp index 47137b4477c5..00efb17b87ac 100644 --- a/content/html/content/src/nsHTMLMediaElement.cpp +++ b/content/html/content/src/nsHTMLMediaElement.cpp @@ -1041,11 +1041,6 @@ nsresult nsHTMLMediaElement::LoadResource() if (other) { // Clone it. nsresult rv = InitializeDecoderAsClone(other->mDecoder); - // Get the mimetype from the element we clone, since we will not get it via - // the channel, and we won't be able to sniff for it, because we will not - // open a channel to get the beginning of the media (it is likely to already - // be in the cache). - mMimeType = other->mMimeType; if (NS_SUCCEEDED(rv)) return rv; } @@ -1084,8 +1079,7 @@ nsresult nsHTMLMediaElement::LoadResource() nullptr, loadGroup, nullptr, - nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY | - nsIChannel::LOAD_TREAT_APPLICATION_OCTET_STREAM_AS_UNKNOWN, + nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY, channelPolicy); NS_ENSURE_SUCCESS(rv,rv); @@ -2424,21 +2418,19 @@ nsresult nsHTMLMediaElement::InitializeDecoderForChannel(nsIChannel *aChannel, NS_ASSERTION(mDecoder == nullptr, "Shouldn't have a decoder"); nsCAutoString mimeType; + aChannel->GetContentType(mimeType); - aChannel->GetContentType(mMimeType); - NS_ASSERTION(!mMimeType.IsEmpty(), "We should have the Content-Type."); - - nsRefPtr<nsMediaDecoder> decoder = CreateDecoder(mMimeType); + nsRefPtr<nsMediaDecoder> decoder = CreateDecoder(mimeType); if (!decoder) { nsAutoString src; GetCurrentSrc(src); - NS_ConvertUTF8toUTF16 mimeUTF16(mMimeType); + NS_ConvertUTF8toUTF16 mimeUTF16(mimeType); const PRUnichar* params[] = { mimeUTF16.get(), src.get() }; ReportLoadError("MediaLoadUnsupportedMimeType", params, ArrayLength(params)); return NS_ERROR_FAILURE; } - LOG(PR_LOG_DEBUG, ("%p Created decoder %p for type %s", this, decoder.get(), mMimeType.get())); + LOG(PR_LOG_DEBUG, ("%p Created decoder %p for type %s", this, decoder.get(), mimeType.get())); MediaResource* resource = MediaResource::Create(decoder, aChannel); if (!resource) @@ -3514,11 +3506,6 @@ NS_IMETHODIMP nsHTMLMediaElement::GetMozFragmentEnd(double *aTime) return NS_OK; } -void nsHTMLMediaElement::GetMimeType(nsCString& aMimeType) -{ - aMimeType = mMimeType; -} - void nsHTMLMediaElement::NotifyAudioAvailableListener() { if (mDecoder) { diff --git a/content/media/MediaResource.cpp b/content/media/MediaResource.cpp index 457957d1ab4f..db01f70d8b6e 100644 --- a/content/media/MediaResource.cpp +++ b/content/media/MediaResource.cpp @@ -688,24 +688,12 @@ ChannelMediaResource::RecreateChannel() nsCOMPtr<nsILoadGroup> loadGroup = element->GetDocumentLoadGroup(); NS_ENSURE_TRUE(loadGroup, NS_ERROR_NULL_POINTER); - nsresult rv = NS_NewChannel(getter_AddRefs(mChannel), - mURI, - nsnull, - loadGroup, - nsnull, - loadFlags); - - // We have cached the Content-Type, which should not change. Give a hint to - // the channel to avoid a sniffing failure, which would be expected because we - // are probably seeking in the middle of the bitstream, and sniffing relies - // on the presence of a magic number at the beginning of the stream. - nsCAutoString contentType; - element->GetMimeType(contentType); - NS_ASSERTION(!contentType.IsEmpty(), - "When recreating a channel, we should know the Content-Type."); - mChannel->SetContentType(contentType); - - return rv; + return NS_NewChannel(getter_AddRefs(mChannel), + mURI, + nullptr, + loadGroup, + nullptr, + loadFlags); } void diff --git a/content/media/test/Makefile.in b/content/media/test/Makefile.in index 377d38f4f94f..5a8df18587d0 100644 --- a/content/media/test/Makefile.in +++ b/content/media/test/Makefile.in @@ -108,7 +108,7 @@ MOCHITEST_FILES = \ test_seek2.html \ test_source.html \ test_source_write.html \ - test_source_null.html \ + test_source_null.html \ test_standalone.html \ test_streams_element_capture.html \ test_streams_element_capture_reset.html \ @@ -127,8 +127,6 @@ MOCHITEST_FILES = \ test_media_selection.html \ test_playback.html \ test_seekLies.html \ - test_media_sniffer.html \ - contentType.sjs \ $(NULL) # Tests disabled on Linux for frequent intermittent failures @@ -215,9 +213,6 @@ MOCHITEST_FILES += \ video-overhang.ogg \ file_a4_tone.ogg \ detodos.opus \ - short.mp4 \ - notags.mp3 \ - id3tags.mp3 \ $(NULL) # Wave sample files diff --git a/content/media/test/contentType.sjs b/content/media/test/contentType.sjs deleted file mode 100644 index b6eb757c3c9b..000000000000 --- a/content/media/test/contentType.sjs +++ /dev/null @@ -1,77 +0,0 @@ -// Parse the query string, and give us the value for a certain key, or false if -// it does not exist. -function parseQuery(request, key) { - var params = request.queryString.split('?')[0].split('&'); - for (var j = 0; j < params.length; ++j) { - var p = params[j]; - if (p == key) - return true; - if (p.indexOf(key + "=") == 0) - return p.substring(key.length + 1); - if (p.indexOf("=") < 0 && key == "") - return p; - } - return false; -} - -function handleRequest(request, response) { - try { - // Get the filename to send back. - var filename = parseQuery(request, "file"); - - const CC = Components.Constructor; - const BinaryOutputStream = CC("@mozilla.org/binaryoutputstream;1", - "nsIBinaryOutputStream", - "setOutputStream"); - var file = Components.classes["@mozilla.org/file/directory_service;1"]. - getService(Components.interfaces.nsIProperties). - get("CurWorkD", Components.interfaces.nsILocalFile); - var fis = Components.classes['@mozilla.org/network/file-input-stream;1']. - createInstance(Components.interfaces.nsIFileInputStream); - var bis = Components.classes["@mozilla.org/binaryinputstream;1"]. - createInstance(Components.interfaces.nsIBinaryInputStream); - var paths = "tests/content/media/test/" + filename; - dump(paths + '\n'); - var split = paths.split("/"); - for(var i = 0; i < split.length; ++i) { - file.append(split[i]); - } - fis.init(file, -1, -1, false); - - // handle range requests - var partialstart = 0, - partialend = file.fileSize - 1; - if (request.hasHeader("Range")) { - var range = request.getHeader("Range"); - var parts = range.replace(/bytes=/, "").split("-"); - var partialstart = parts[0]; - var partialend = parts[1]; - if (!partialend.length) { - partialend = file.fileSize - 1; - } - response.setStatusLine(request.httpVersion, 206, "Partial Content"); - var contentRange = "bytes " + partialstart + "-" + partialend + "/" + file.fileSize; - response.setHeader("Content-Range", contentRange); - } - - fis.seek(Components.interfaces.nsISeekableStream.NS_SEEK_SET, partialstart); - bis.setInputStream(fis); - - var sendContentType = parseQuery(request, "nomime"); - if (sendContentType == false) { - var contentType = parseQuery(request, "type"); - if (contentType == false) { - // This should not happen. - dump("No type specified without having \'nomime\' in parameters."); - return; - } - response.setHeader("Content-Type", contentType, false); - } - response.setHeader("Content-Length", ""+bis.available(), false); - - var bytes = bis.readBytes(bis.available()); - response.write(bytes, bytes.length); - } catch (e) { - dump ("ERROR : " + e + "\n"); - } -} diff --git a/content/media/test/id3tags.mp3 b/content/media/test/id3tags.mp3 deleted file mode 100644 index bad506cf185478c9c903793d11d95f278148e007..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3530 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 NTKS!Ea=r9_;18hDy14)V diff --git a/content/media/test/manifest.js b/content/media/test/manifest.js index 12219067f143..d5674d38c273 100644 --- a/content/media/test/manifest.js +++ b/content/media/test/manifest.js @@ -151,19 +151,6 @@ var gPlayTests = [ { name:"bogus.duh", type:"bogus/duh", duration:Number.NaN } ]; -// A file for each type we can support. -var gSnifferTests = [ - { name:"big.wav", type:"audio/x-wav", duration:9.278981, size:102444 }, - { name:"320x240.ogv", type:"video/ogg", width:320, height:240, duration:0.233, size:28942 }, - { name:"seek.webm", type:"video/webm", duration:3.966, size:215529 }, - { name:"short.mp4", type:"video/mp4", duration:0.2, size:29435}, - // A mp3 file without id3 tags. - { name:"notags.mp3", type:"audio/mpeg", duration:0.28, size:2506}, - // A mp3 file with id3 tags. - { name:"id3tags.mp3", type:"audio/mpeg", duration:0.28, size:3530}, - { name:"bogus.duh", type:"bogus/duh" } -]; - // Converts a path/filename to a file:// URI which we can load from disk. // Optionally checks whether the file actually exists on disk at the location // we've specified. diff --git a/content/media/test/notags.mp3 b/content/media/test/notags.mp3 deleted file mode 100644 index 7f298131aa437897eb7ff41b64ddc452ec2a0ef8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2506 zcmchZc~Fx_AICSzLrB6EF&rugQI3F!;SfQvPY5@Hgorg(S|A?O9z?*lDncHD+_z%U z4!7m9Rz>VfJ!(RbLx_qLs<yU}QVydML1;+`*%vxx-kJCP|NYGD%+Aiv?DzAV{p~DV z;M@cMO-RCF!P1)1($E8d+zZTBa9$x`h4)uDwnF|2bt~Lj;qeNSE5H?&&hiTL4G(a0 z_VP@^)h|bKwgiC2vOz-F0I-&G$a9|lZ`kFX{{jB(Lp-=K`dBHzsp)UN@Zu5x==<`+ zo=$$tKA#+5Znw@puyC!59Inn7nfD}FXe<yzVHtv6k_ffaUNcGv8B?TKPYXj`Lb_z+ zD1!<Bg<+zTteQYm*Z%R^?S6sG{l1&yZso^u<(L#F0R2=Vfi={%dB^DuIC{;#es_;~ zgwXL9(izM5<yD|>bWAY`2TQjeX~q}_VEd{YNs=6%M@eUU9De~$AJ*rVl1h&YD$S~) z%I^B_kF3sK4aIaet-ZhD(_8v*fqM_Z^wP=scfJEICm2_J28zZip?ts3L_+$NMMJad zemT!$Z5qw5V~0iQ9XS#hGuVE6(QM9{^;=TgP_bLZ(Mz1;YK!r-kIXN0ujjqdw0?%Y z;qj;{dXRq&^A!3!=YE%ujr~%2!8TEegG2D}1;Pw5WUiQdVQ9`tuxltRkk&X0(#fir zaii6W-K%E>T&#{=m9-l>Mf{XyIF<Hb6I}ZveD)IlR<3B8mi>#E{+#ei+4GUdw9OfB z2y^x%^A*;BjBCjBDeUW57SaKFr$$eVR_v@zt-L(9I?qAON#f;eLQU{Cg`@Q{Rr@O4 z*;OLfLvM)$VHN=h7?D;N&nhA}JW_ORJar{-j1e2-6k(iqmti2%-Ei>(k;K=#o$q_# zE8AV7Zdwh`Og!KS@F0bV-(SX0tH~nM-~S=*Rbj^Sr;~%cVP7YEZw1X}k4A33Q(ctr zpEaxRq<p(6H8d_>okNN!%N=J@U5rod@q-QJs5ISJFp~>AF-smjQM(|Po@tDBKNF01 zWaGfz7{>RhgR*~wDi5S&(%$n*v77SwG52_m1EF{hant4zUY$(tVIQSEOz5ySAmjO( zO!8Y6$7?YR**5w5&vz~SQh5_99`w@%2L*o6wRRo%9Bo3lKP@UDo>`X<p4|NP-kJ87 zpKybm>DD9wMp|u$iz>GsIsN?5H?OD#&{DsA5sBNZZ4f=)4BKW(yfqTv0I}>30XLJ> zGpygO+Sl_d0Y@NN?^kfoSD!1odh1&3h~!a6P4j%tI((?8mg$eGWmy}nO{_5hsH|sn zFTa0;64Asl+DUmDQ|aDfB&aN|lG>O+M}v*R$*|!H|5c{KW=7T3g|<l>B4R)3#28kp z3M}!IljdDC`@zm+$j2KKVduN{=(7vqdXF&QFc(K&l>x!VHoc}PLp4&0FxeUPA$W4! zqaXc#{=}`d7!IttQ}!fcvb1=wWs*;NsTNh)6kq&SIGbpo%BBh*ciS&mO=X+wD;F$b zkiATvP5mOqt>ykqYlX5ow8L^pb03a67#1lzDWcP!DJM5#41;T>A)Z@Kc>FCS(rZ2^ zXvj%fbL^YfH(GOB@-20J<>McgU*;FPdZ+DLe*{L_YR_av`Wp352>TIcmKrM{ZicSn z0gR2FGZLQfLu(5jvbQOUl<@PtN=4K5l<GZ)w!P!g_4U-77sMbDVAA-t39mdCi*qJ- zoYwsl9b?5l&7Ka{r!V5IKL{6El0x$Z{cb{OKB|ynWOZw)HdfkscIJX)4eHXv{_H~z zCRw`R-j(XIhCo#Y%_X2Qb<FgDIQPBP&^4GstpQ9x+=(;>|LV3ZL<E%jj}yl$!sUCN zr!=)jUmIE0{NW`0z2<W``3`(6rEgJJ5JYUNhhE}dsdCX@C=)6;)BvH3e-jOfR;tOS z)WV<Q4^(QpxDKzIL(RAA>CWYQbE3?<N|FG{I=iT;Vzi>;;TxG))s^!FjI=(hk#at^ z*GjKN=EuX^!X}dMkT%`FC}O5jRlqpVHdr6EF|DXueS;C;^~+y;;ibJ-U%pE*cDgrJ zjLf@7=>pNxBTWIw&7fWBJ3bmPW`)--8sYG7(O%@Ra9PL@qa50CWJ##qziG>Ca_-%3 zHr`+{$p79tP4BRr6+jXU)+Y%swyE+Y@!ndl#e_E7PyB=EbY%P(&#D*8ZPZ~|cXKH& zlPsMLVP|#|lY>^xuG5915?<@$yHTNTT23fgUwb*&*6gaL5puD7$SvcvX_wk!kWtcM zrEVz*gf0=PCWJ=v=5Tgd^$~15-StZl6MjD+vN3?HIrS3d^`I~kj{p`crEPm}yhc(6 zj-iVL#9o^Z86-RCfQizp)n3udLTdrV1@~D)Q+SI%UBJAUS5+-T7$o+sj@WF+@<hfl z-BAO=RC`^VS)UV4*W$}}z6KYfH)U3JjLPbfTCrA2GWJobOJFyP#&8N$TVz;Ek7#4t zhqe6kg_>R}4~I5~ir?Z4ZT73%K{qe>_B4ZmP>%;!#~$-o(??)$%}^r-6n20esiE5; z@0oPB9y*3Q+6N!3CxzUGUu_@OjHE?C_YQQtX1?U=V)#;*tG{{}uP)qakb8dk@dH2f z?YW3W1NWQ)a&JM*vXC7{9((`9jbzN_=C>~<?E1me2@H@i62LL9QwmO;OVkEM621)n zo?L5eG%xuf3Mnz($PtnJI_1CgR=X-bVP|@eXW*XSdD=-=4U}J=d0{?1pS@dQF@!pQ z=UVzYu=(J?!_q6)l^>KW3?@90?JR70IoB4m?WY|PhZ(8S^4E9knM4j@VZZR_r>WlL zPuG_w(rxdV={{*{+KS`o;9{c<GK<6sTjY7BP@Cl2w3S%*4OBRON^`pQK)B%MCWNgt zr`ucMt4=*Vi{F-oY%?hOFPu-!0vuhxki{$lwwh3i=<>IRg6MQn7Lnu`bRw;Ad14;K zMi(5fOZdz%iiwE{&D7M?2;WYRi%Tmx7!|drsx~f8&>66APESuSm0wpU=3HwP@-D4> LXPn(H{U7)@tPzX8 diff --git a/content/media/test/short.mp4 b/content/media/test/short.mp4 deleted file mode 100644 index 0b9870bdcb500389b78a84e7feb6cce31fd828b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29435 zcmd432~-nV*Djo-l1hMtgeVZEBnVLkfq;mJ2nnD}4#*@TLI4L;Xi?FQ%8-ySi-0mY z5>b%JHXtJ1(vmPLIN$({U`v5QBP|jXHH`TS?f3n@`+xVl|62dLcdhGMtV$|X=bYMS z?`QA*>|G)d2;IFgC!+TsJrspNpb(2k_|GaT+S(F<K;ZTs*|P_MIFuf>J2VD?K;A}> zu<)Ud#K{p%-!+W7`{9FFu0<iA3Ws)c+y?`U_>kfSjwMrkO=>e$y@+k+Ew|hmsl@8D z>Hm7%0FX5Al?uELZ%g6HnEjBn%(hIj9+1Q@5V1(Pz3W_wWV&cJF~T0LDv~9<6|}JI zf{B`n2l&$g{Xo4^YX6~Ey#>-g_(3CcdR+B3B%QL92l=IPWHKc&u|V<Qx$l-UI-FgZ zZT;~b{Ai}8FWwuf>E!c%6NMEp*RmnUpRoePCN7bPT*sPB_$IIi(Ntini|aV)!r^jN z`mh;_2Cd1uUJ7FW;t*~zYo^)!1U<rn*9gXlDTEjKFxt|cYacQ{$ej_J%ljiWo@Ca| z=bERoAivP9(!{fyoUo`$<#_y3u~xK~K&mK3ie!rMH2P%1S6-K<NEIvKRp|rG5<5en zRkB=jV}EF2h)&d8)ZNLtf!lQs;70V7-bHc7E7Q4-Q%xj$$N8(rt5j@=S%^*lT!iH( z4}b)A>qZ?|nui3SXy_Wn9y<ZaqG^JbgpMHMdBuGq5-78$$)QP-YJs3t@d+@9YJ?Yh zxe*(TIh_1mcubBr!1p&0G)tCuIfN|C_-@Ipo7Rb%H8lrOWBl}>S3l(Ump~H#k%(O= zlu@au<NP7T1Q?6u&0AB6bK59XDxiV<e(L+$YO1>ihC!W0d4)po+I6uENh<?_C7twL zT8G|7HSP%`*{TQl$T%g{I9=r`V>#1X_Wu^tYk&_yrmzypRMQZX(Mn0r>IT~S6TZvo z!*~`yhri;xsEQI(sl<7BUx<o`U6rWEg13?-|6Ig}LhpW8wB#lPtZ1$D|9wK5{a*-4 zz9^*c5{V}wXCmM&C}!H*gDZhn#T&f5|GNOfuQqnzZR~XBM9oqmoolP=$xru`!ctWE z!r29@!J_81(4$SnHz29!zoi9TT~u9wJ*em>vxgMp$a*XwmH3nRgODB>IRq_Hxwg2) z3pV}mG_U$;fB|Z2WGw!)k|Ty>Pn!wFQE3ZZ_xv&6E%Kj>zU$9YLHcQ%?>c3SRi{WH z#{^hM=con?-can*c^Ma{$A%Q`*i>Fj1Jy#2t@V$9<#saD(`%r=CBIk-P}#c5)w)zF z(uV&@@$GqWOw`>6@FI5n(4dij4A7nme2a#ax}7JJEvbdgn!8HICBA@1Z&ibz!jeO^ zSdi`ezR$C!-*xD_I#KcZ@Pi%+!h0`50XL))HSzs1zxwL~e7__|P<bbbFR5rM5@0Ma zIQUUH+C<_)?^*cb2!h0xs)`cB3W6BTCTb!Icm2!OU?D&GZfHMnOa7l=tDhcV@neSL zl0}eO)E&ZieM*Ooj>#nsNFm4(o2tmIr>#=NQc+kh7(k>$bUh0gKi+{G7d3TuUA$_8 z@>{}pF>xf<v8XCnYzl9)D7JBas_gO)Ay(B>R4PE@qkANhU0#-+SBS{jdiVjtC0wr3 z4=j?~W8cF_IFu@p$tdFQGJ|ahw&c7s$qFN8@93dV0wPF)&1J1QXuLRogGD$0=YNFw zFS(fg3!VxRg^LD5z@{i7-QkOCK}Z({wE!o0X)$it4BjU5f2j~W&A#vYv%Xqp#Wb8- z%916#ht)M<)@eL@rRI+r)^WI$C|Owc;cdzP7S;bQEP^%ptA7w4(+w>BwFcstmr+Wd z!oc$yegI3z-X1;v-KOUL6Mo|Z{=x6>Ce-enkV}bNMDP>=3?<RJ1;ElpEPSImCb{>I z5dS5Y{D0e<)M*jxKtZ#j&Je!14~YJ+ko^OQ{#StgKttun441|BcpJH;n{8S1zeRN# zwgVa0mM9%^95%;3QVd{u{FgACMsriKi#RZi%=r!iPX+|HQ1#8<^@zeWMoKExq=V3s z2%3c=&Sb?8E&Kll>;F4(XtxUH2hu(1rGh%Kl<T^_q5l?D8*B%1*m*#cv`+=VNWz3b z!Wx6O#n#>hD1p7n91lj9Mg2Uq7z%`b_i3kpL;?^T3Dm-o!2P@>*P`w(BI!TiWAl$D zK{DFCMYrq#Yy4#%w{ccl1UtA3@aRUT;jkbBu^1LO{J_V6Me8DbH#8ZHpQ^xFDD12Z zzNcwEKr{9qkM}Pp)+<!S_%EHK7;}waM0<hg;wF4;$%Zdx{e+arqSay3;bL8Q+<J7= z==atC12OHA2a<C?;9BaksC%$2Dr(KE_?-LyJxcRrG>Jeei6^QljH4a)Ey({%!1T}P z-#xvK>=?A2BIUcOVgk;<P<RnBoiN+72tuF!kK5SD|9@9DUsB6@F6Pi5Fb%Xg`vaKK ziyy*Xs|I2pD*m#2-Vb<41<7narSo4O9-GOIbUAEQtnI1$F4bObf4r_09@n;ww%ngC zAe`U8&er01CrBVRZbKBn-_pfow4Jn7>D%c>Fa=R~0g4&iJj{`>vpE}876)7Tq_*zg zCwgP6C^&dDX)OFpxLwbGC~iuJlqaA|PHRe72Pe1BPDrd$`q9p+MC6<*WRJ&=N(X-! z`k#D=e)zVe<YPAlZ~MbnSl>0V?$%zdeIV0Ba>t%f0iw(Rlx=lM-L=izu5BwVdl8^f zuj7kH2Y~44UvK`1-r%3Eub#-~+RKmeeAp2Z$#t=M*xCSlLsTR%toV4KF0kh4c!Yzi z!p!X9K1qr+89e;su(Mvp-zT{b7T<75-42<)ER>)B<4{zuvTF<040xyb^zt8rS?fO0 zQnhnDyY6_|8@qe_CjcRuOZ-y`t2Q;7s)6$7FNS@K;Bw`V^u9qzcmg(&*UDQ7vIiX} zz*C-w>UAMz_c!1YsQtuVJe|#<_c9GI<7W4vqr7JS8;j@XVu|NL6k$>7FMoiwM@T|z zPwJVEK7rO!;U50gpV^t;5gYLIe-VDM=OXqYk5O{B<KV`u+@4I6mf`$ZT&%9k^Zw!0 z*IePV7h0zG@`-}f3x)r(#p8xHJ%$gz_I>^K_o2^5hE-rU(4-hCqpnay|B58`siH~i z9?9)#v&C+3NDtZYIQF{eK^z>&Jd@c6p+b*%MiMHpNs7l__FESQj{*nyg9)E~iAxmq zK>=?eXK2U-*24dEQqm{lhRk&XEsBqt;h88JR?T^o=Qi{0k2>t2tkm_7`@c6v#GTxX z@*F3$NZpL>;Q1G0S8h-^C*aYZevW7IHaH6qf51D!v0jOny*;WPcKP*~`~Pu5498&6 zDn#UYI7k!1LE2aTXUA{Y?9i2PoRiJXn(c!f$_TTqAIzp2EoMum?Xc^^XCYz7;RXjl zJ5qjphvTj9-`#m9L32<ii!Im)hi=mt1jin)m&TD^V@)T_we6?_dCNA!Ai55;zzX<i z66}9ym_o`Kd@vD<!s)}ggM*4qv@__6oP?B6F_fjALX?b~FufBFB@E3CqQu+L!=%E@ zy1yQ5>QIU1;tXMEd=H3ZGL=%;RX++;qu8U>AX&l`zl+PoJcm8{$ev^;7E?nKo3+5| z2T8ELJ+=Ui%)gJ9Stl){T#IVVB?Q=G|Axb&M?xl-3&4p+5CGMHG&nklp%SOFlVObG zI>EQZY6K~ThetK6h6AP?HAJpS7}CgBfMIg1?LZV_GGs0Z3IX^m5^|8Ej!jn#XU7iA zzoPIw)Ggs_4}pNQh(jl;D;|Uh{%03$u`bT3^DZ8C*V=D)OT(tTx^uHYc^pI1Eo+xd zhRoIwFDg2j`$0hTaEjuAMnvmLM^s1G_-JDL9>gJcp3W;@8A;PXi1!O53xQQs4fJZ( zq~pY>LnLZ27Y=H~Tw4t|Lil4bwpRkV_RVzL%emKvx=-G4AvI8?7ir6>xWP{w1tZ8! zFF3GI6rg%G5`pOhVr~FwQ3D%A(_&>Ym)7YgXp$tuDnCDuea!O{*RI>mkvZm9Vw3m; zSgmJgh!+uMqjcB_-hXiBmX=7gKZ&4mMCnwq`KbL$By=~@c+2^12`NgG?!4@V*uvvo zvB6#O5=~v;FA2HJ63d_e0?(*C2OGstf)NQ-S<JDO*b~3fd8)uYQERSFxu@U*e-5*k z>3<y$3@JW7$MO<iQ&llyZq}C;F}EJYzNEr=oCZjt)3ocpG%Mxf7eFVx2VTXCg^+on z(So7w4Xqc}Mrf&UrW@yKFmM>PG@7cp5Qk0UtwDZHn1y6aBgo!jZicu7@e?qj_^KYT z4m+Osk|Omjq`;Z2V&!Qnh|z`3xQIQ(AxL5e7M}Zd@tW~J7X!iHxS1O<nSvv%WJcC6 zFVj2MKrNZTh=k0v|C4+-ChqFjITgWZ!pFA$FrLhDFcAmO15J8i#IVrZ>;T^A8KR0J z)!r9rws=!2FV;hyDbF=Am)sJv^1DoM`Zx+(EhWrL5P%6hRI2+_BVQx+D#yf{ic&gm zCDX-430fp;c+-tD>Fl5fhDn*Fp?4Jgi1k?rYiG3!J=ljX#JK7QR?89f%q1%4ji{iK z4RSEyStNBivH|;8(JhcjmrLv|X3YLIOvNK`FxnE%F%~u;p@d&CM(}zU=g@F~_nvW~ zmWslCwTjWjE#9zdao#E-fYw3C8vm|?rS}Au-bhWg_)-s{g~x)!%u7`4Y__+cNzvA8 zzX=%*#rC3hphm4YdjjxH)w8ziugQF>M{@nq80FO-*&i&dz-G?PUtE8`(n@Uw0jEz> zZ||JUZ5&cLi5F5tG%DhvDy(@=ZWk7P5L%pS9hllK^BMnj#Pe9P3qoFNM?y%<K6!DR zqx>JJ0)O(y@=T`Z7OXM38rViNFT9Jk&#_g?-8Ii6Uk<65%@`hNlRTAl@JvU3zd*On zj(&lUU<Sl_C$#yP`qC<;m^D)M>c^qi1ybyzJXB)<0PvVJ0M-AI&SY=Dcb~_-xpji| zDqL;N?HPJaN27HBHQaF}NJzR1ao9b*<$XAx1=E>_+p9QowPSfm*;11T%-#%#E2c!( zO}8g{#OrD)8#wCsK@(6-3k5Z;kP0^<_xky0SYL3tr)|EQs*F5#WY~={ojVZf+ADh} zR&%W4Crh(q)kTt=ubOP0+(;c*0s3Ex&rX=rD<~!NA(0-iqa+dKa;3|kFV?@%s{uNw zBqJgE&u!l>=-2gVD6n?+PgwqO7I)>!HLoZ4qV7Tubg)glm7AU>42S0*uAKO5q%1-$ zVj1Bj6OU0x-DcGr3rV3%DP$*NAfSVtDbPxqJbnK16;LN)S-$+X0yH%<^RUG>D+b2* zBKaG}iDT7zJGUkMI%u$CfuFem=pTGzW&#`HmSBN|^|A2oLIk};p>yRkr}^|1@2eik z>}HuP^1(@bY8j2FIHnUBy;j<zx!37K_}=O2xe_N3N0((|1%xRvUX`6Qr$rVu)Epi- zSNgSd(6{hq`Q)nAMF&o|QT##VAYF~a`pkj+#DU6fSh{4zcoduuwRd>ZY3F@Uu>;#q z?*C~*%mRa|j>>kkU|bbo&Ow}QL=y#ib!GgwYUbZQH@Zd%qx{S~Wb_`sAP*tQt%FQ1 zR`hq!&ouVzY{gV(V%8a3y50vHs3npqiVKm=-)|Wh%Q>a}t#QrRjskZ2mz~Cn(|ef# z0W^kxr&4ENl*k`=$65jtf!W*t$<+S~BA?>OXeDqAUPn}0s9)q3+*Z936~kURl4_th z&i+hS(gew{yL$yQCvevPbRm2(Z-1z{4<-y?SNIROONSs8@F+({+WD`c^5LNZRtcrT zY_6>`d&qGj0wx)vtCosn(F6g~2Km`>I<xMvMrK|61)F|;x=xfV{Yk&U;Z>2DEiK8G zbpsvUnZof(9i@RM^Df`UR?MG2wA*6K#m9B{#t#^W2;QZW4^FQ4tUx?%o`_rK+j@<U zSVsj0SsI`I1{5Xp`^I<udNUu{c!1?&<XOM-Q#Y&gEg`=apR$1AXn{v(gU$AvxGC@5 zDVQJ1{E1n}R<t8~j|YNCf%h{6%vol=B(B01XwCfcchpaj-*W$wrY|`7jlAGzVUunq z)*iiriC`MWUAN8gTElddGx<f0n0=;)Pg5&A&M*I~bNx^$&?C(eSE=(P=Qc0LST|5_ zV0P+UxV7%w1-~lIRiaQ9_c~jbPvUqSD;cZ0c(Infa5ocWkU&M<VVUx-(K%WgH%L1o zqw(CoUTuf``{&K>`}Uf88mt^jtVZA!(4gG%YBPo<SIo^9_w7C9({|o0vfQyT5#@0$ zA)Q<{y?1(9rc4X=6AcuzwLYt=Drc$RJ~x(6-B}%Rq|-yoRFOf^Jrw{Fq-XNviMaIP zxh-_Yub;YU{x_FL#5ZeGYiV*V>}mlIa?)Pv?s<1KlV8n6xGxTW;!8WTuOKTVxd= z(cG<@vx@$J&o}t+n^Vv4=^5&p`!eJ&JZf3re8YrtjKf-=Oul#}RnEpXDPE7Rv40)$ zyLbb7>-_TRjEg-EO|f6gU!zJA5hw9F0y=EHf9^d3O-0+!y62TWO}yP7SEZ`bU9umh z?=+A!91UP`So;=3vmiXqps^Uk)K)Z(oOp(8+$%sej+g5K`nxF^<0fnUZ{9g3`YCer z#gTAje(Ug<Z`myJSpt7YCO_vvVp}X_<*JXV$cc7?2?llZ+-AYB?E|LiTp-Q5in<I@ z2TTYsNlU~;jAAEy&UAZu-ie(j&s*dfgSt%R$KUwbL_yC^&_%*b#p@;wyQoR{#{2jB z1}MLTO85D_Rq74(`l~f_TA!nZi8wB?BK=@yzH>itZV_OwtHPP2{k_NnqXp|>y6`z0 zf_B2(ThJm~WvKNLl}c4b!m-4BKlTxCIiSRmC47L(2FoQ5`xLM>e5d*B(Hf8}8uob! zzc2)?5)J%_6r$gS16tTr=MS%>nj^&fyh08CQv^K#drn<|BiYRRm*K)InzHF1)LaMK z+2fiuOW^eX)1C0pbqCs-e*XNs+r_JE`f|MHuXps_Ou6U!Xe8Y1$f+HmDnEHR;b0Sv zd4QONIN`USBZ$4}U72Zw@z?Yh6T%Ux^!)sk5VMy>y0vQ~q66rFj*7@*t}XszFX7LX zt?}dgSDfqeFW-L}K+2$Bmvbo_08BCN9Yx-5?|3j_O*CZ##(IzN(PS?FeXxAp=Y*!F zo|KgW98Xg4b?-)<Po;UMT$@x(OppJ~bTI*g>}LEnaVE1jfNE@h#2K3_HZNyN$=CNi zl2`h<HF5j}>Ntc~q%BA&)W{FLV?1f94T@ve&;N9Am#4z2%b34KIj5;^2MPIx#Fjy7 z_gxAdqwa80D|dW~n<@Ka=l-*QHjOYT>%N_>2zPkEOvl$V8S``I)H>Q*4}QU8w<0TO z*-YG4p~n5E_XqM!bO5pyF%7Zv(18CXHQPdmO*AIsZhU#xzCuv-i`((QUS_&2sFon} z7odWtCVxJEdN6*h?*3)>gTaLtkz1+=#<IWOd}g(>hrD(p<T7+)(??VPn++>1B-Zpb z<%+1D`&Ub~WXEwue}Xm-VkFF7i`nas0-x6|44}*oE%=F=_mUHhxb&KHlGb=MTgD`l z;tMHc_v`yPt6i1u<QAO^>rT$iCp6zO^`P%dK|CnrR42118^0NzuhK={`)c>RA>!_b zPcLU1w<RKu(`w7qkp8_CK*>Q_@@xF+54&T3JJq<==O=#kmz$ZAKGw>eBi$p`7=9pJ z!wLCwb$N!v!1=8cA1fX(K9<c~hi;%ZvIDAgl{r&5WT?zE0Nf$s+}X5!y!9v=;a5q_ zdwamDWYD|BmU?HR@=z0zuV%o3bF-U>mu45T?|2^>sKbe>{JZ##eiu4e@4dKB<P=+4 zDqNUB1yaXyGw=M(i^`aetzzlU5sW>0QlRFrufG>!E=KXua5R$lorGJYt4-nL3ATVA zVL8lFq1ab?VeXm!kKHU*tH^i-TyOagYqR*D__z7XVlK`M=EuL=s3&ZrE43aAB<!Ey ze6iQwb!I5QJ_yNq@;`dF*#FVF!KMb6FuM8=34_LAOS5_KdNaJt|L|-5{bfbp=Fe&_ z53PGS+wp4t^Nz-kt4{CTs{wO{ay5I9CwW&(Q$|#u2tUxh>eFMrH3J92dUW1xvX!D) zyY03QJ(7GWO;nT!rayiR+t|H<n|JZo!=8IYH^O79YVoFCcwf!(3+wkDGn+|@vd)iD zKfTR3|E0LdGhR=<hH9-VK=pqZD(O4m_9A3Ur_W@-a8}z=0^hr;`VvSuzb6a8Bz}-$ zU%jiC|L~cf`s9x2;7srEM)A3L+s#*q{G2$^ZuZ}Z-IQtVbDy6jE7E}BkVaZwhwd3T z1toqG`{3vgToCW`Sn{IT)2pyix4(8<J+WM}g0!slLea+FrmgbZZ;NUQKE#RrYkKBr z%MeAk6Ru@_8}j<=QJwO$Psa|P(dxz@q)3JvD<fHOLH0;9LUOlb`Fv@@;oL8l2dSTJ z@jF&0**5Vw^fL9uC=->aLYJKNY<`X2_@Sckog%&Q^xVCUjqjbGcW)Rkr_J+1m#TAL zpm0paWxuv_j0?B+bBsT0T^MK_UOQFTBc`cW9(+_oy$-6fWg@~XrMEPGD}RrN`ar94 z$2n9jYqwZy&z^uTOIN8N=K<cZ#K8Ucp{E5OSAT78^_V~YH>WiGShf-Vx|%gx7ieK= z;FU1a<_XQm=Y0NZ2s|f|cAZ_nrSkw8N(|gNfqgWZxE53kz;Kw1$0XN-wfP@`!_EgB zGx%_zggutcc^@d|xRQ|kLtk?v<D%ocXF?7%KD=4``&-P|q=DV_b-Hmp|5|)1<@ymk z%Cw?+<kiPhAF5RfeQlpAI{1N4e&TPfIN0G3&}C&QGez<|@TCX$DPA^@w-ug_ZEU^c zzWwvhvD8By=TVZI7><Jra^JGOMw21Z^!bSu+s0?&sM5Zhp<8b3wl^C9)Ky_B4cDk~ zYOzl4B{TSX_wBd&20z8*?81E$^@O>2#jW(D5CyIA@1d*PC*_s!ud%)+3i-SuL|wUY z!7<^FR;OEvtbs3+UX=>XqVH#Ko*w!ny+upxR4#-r4~Ygtq;Gt+%76cGXvt7%+GC<r zkZwk+qqL7CjVD{4sH@&CpRgg)5Vo+jL2?pyzN&xi?Z}bGw}1aI!QJ_$>r$ab%4=V+ zkay&SNWw1f?peS)YnJX-l_%I$5h`9^yER?B?Ig#ja=fE2?>_P{_vnl&#th&3ZZheU zPuNwQ-UN5o9kJ17W+>eg(ZvxAuJojtfH*{iz6p-;hRm)IsnW9A|A0;eo5*tx@Qs5k zo|y-h5s4Yyl_kw(T0$cvOklrxMn8$iu_U_6+6?}n(Qkl~frv}NzSBdmQwU7Hb=KpT z#ojxe^|JgkAEIxd3QQ5Q(3RSNL~#Xw9cV&K2Z}?DVv#aWITjJICJzyPmXYQmRpt*n zdDkPM0UAK$**5?Z>-u;GFJeu5#r-M@DG|rqU8XNkA`3LpO#9$qd=T;~o(dwnLS?yC z`X>I!YhRpYVX_D$Pa=Zp%uTUyP-B~I2q2DJg_tZH{UzmOm8YCN!~cW6_X10Rg4ru@ z5U*chj&p{HvMCBt(+Nr>L32QNR_EYJak4TB5)xEi3K=X37wA?}mgBLVa}It8nSMF` zhV(uG&e4ZyfF|pZX|Y>=rKDFxY51)|lvq{Y;7LXbOA^S!BxU~nV8+P^&@X&I^Znst zxbV&(M+Br=>}BLchQ)=0dm38d?|zUF8;^Ar34^OB$B~lWU{WVPPoSD2p%M~V>6MZb z-h4PrMB|pZG3NkwN)wBjPw*2cv09-fH#*vmRA$L#(vc90oG0NVlaMI`xEKJLC-DB_ z3?<_o$VOB51t#QfKvgP+liS148kegpQ7^<qG=h(WI5d9(yo^q;E0n$zn4Gz40a41R z*m)TXNMtR@wOGy~i4Y0Bq^c~4IZg<OV~a0$0fB{kl30rccA{2vHl9Ijx%#Qv2#_{@ znlz*n^CUbXfSAZDkeYi#LcAl+V>BB%)|mp=7>NR}WD;Vnn_}TA@vS1OC2=_3H;5=u zT*k4q@yI5YJszYt`GE>P8_u5B05Ca3=5e!Ok?{y$;Ee4r0TByHaaw`ZhWcF`F9EJY z#MCAGmHRpfh6asv*w_8F1c+#>s|HfUQhmIZ7gO$uRwfuR<&*{rvE0I+;WSo7QjzAF z<et14l80U<3zgAh=|ZMGT*`IF(PI;2952_><pe*uhi?@<D<hF)kDZ=!2YnrYL40f# zz(;7aN10RgZZt2J1t^l@V;#WTP&{O$&Yv8m`b`*-=kUl-yuN^_PL$aH<|RO~kj+rC zArJ+cllduE@%l|rC}er01kpMsg&O}Rw_p2m0L>DXk!DJq6G^K<KN%;H0muEkss;+l zg?EU@WnuZe(?A(rfFeyTHIN;!_a%)^`&amr=yOXQug#N%Weihzt!Li(B3Uw$KAi3! zKsIg9P_PrV#XN=})&neNSw^${VJ=prhht1>3#`lNr@B0RuLhh&CI&cB;{w(sBCr*p zUqur!x5B<~Cyqlkgoimv7@8oqh!5Zm%hAka2eK0a-kjB5Y?>FZY-zYcQ&SN88?g!P zf8E1^JPaf)G@RgO!`m)DYnWzLAkfT8#PVcTykz*4qH$2sBId03<P+S$0wT|r5`%>L zCr8ii_8WOafK)*dh2(^@60^w)h)a{hMStvqdMMgmK9ff8NRjXu1qGT&S<;}P{?vV9 zXNI(vLK2DzB3;s)1KIWM&?hLFQ3R4v%2&T-bf+=h{q5nMr0DbFc+@h0UF%T<Vn`q& zG<qh>FRSG&q>AX;!&d3YGp+W@u5$NxBugh9zbP^vw!iyR@@UPPCd4R3>{{L)Oom&M zPI#RL|4JlH(T7T<YSl9(200(6?(&)dM=J3sWq-+mn855aj1^zDkn%K3Cy%go9rj|M zm7ayZ<b004kA0Eg1O%#jRJrTg*m^wu{E$zs-qeMyl*zceu<0$OEjhE8@rZ9Tul*TT zH%q%~pE^94eKevOSao#0Xt&N4x10Vk(l5vCiboPP$3lq5Y{!@1E`m|5$`ym(l*611 zu4^&hI@O(jL9Op=Sg5J#63RQl>sbDMyUi*s7hd3{%ZR=1r_mb6YTu{SI_X`1d4*Qe zc+l0Xa=Zs?ysY#V>(80GGPIVvTovfxt@?m#eLH&jj(bbApUv~F%fr7E6}&wCi-WYM zjEu}hnN$yzobs!c?hj)rnU%b)t2SE3)!p^Q-K83TYGT0mO_AI6dXLE4@A<g`GuJnn zM6n}nNIY#-JaB~t6h;zDK%&(5W>(&+#K34DC4vbtZ!9mN%^}Ziidc#mn(#PVAVoMn zB+ngrSVVYNMdZD!xIp_RMT%H%_J9Pk?Q#z9xCoLwg{KaixGYffOUfM$@Ib~{08Dx* zsdbR&cf?dF`IT(rzdDX83fNE2UWXXN2N<;Od0RYgCX=6Bt9Wk6ai=W@{(#cYIjYcF za(eSgu1Q~~b1a&RySAk&cM40TL~rCEE+%ig@VrjF!R-S(T(7;4eYE-7vz}-cXv?J8 z+zfD%XWNqfmLGaA^YFFX{0>%-$e7C_>&nL{gH7^!*XbjnecY$s2^ac3r2a>n!$BKW zspsS@b&@j!<-gviErngw$*%Xom79;MuW%QX<x-B?lmSty{re_`<13Q4#s$nuetv9o z%TJ86C8=BGs@8%j2c`&`waT@{w8Bl7+&o>XwhD?RHZ9<&(6HutZOH<-o_WHa<YV$$ zI{L--o5!~|pQ1#mBs8CLDpR$4VxoSa{b3VkG&f|&=fmFqofkkA++NGVyxdC`W_oLW zLl&dz__-^h8f(D18?&6!?(mnVg>;`22{@%2!u%z1)(OciqF#qj(P2`8?XuGOYf}QL zF<m?TVyIQzlPs58(bc=W`?Yrrb}^St#rH0p`7C?b!>^6+yZ#}oP%rVamH*l5YnRO< zRdMe#{E!s}s6v%m>2aGJe^qvF#m$WgE;*x2acG3|CTtDyFQ00^+H*6YwFlW%{)^In zsc(++{_~t)^ERjcSw2-y^e-DC?nN}2q3QU|*n+q6j;kxxC|=JGDFK6Tm0L8#^a|3f z4{o#gy8gGvZE=c-9PKSTmec@_lcy$6*v?(Nd1H6BO*UKY9J2SUO&R6LP1}4`bMiZy z(Dv52O&)V_SsgaaSN6_rd*KTMVMkt;XLX>zpUu-?3+czvd6R03&x1<Wn|t(+q0#Rb z@Yf{V`r}<}>gcc!XYkwPc83bV**f}PyuL$T;qTfLtysx7w~Weu_liGndf@pA(hdvN z7uG%3U!PV2=7G(Xn}Qi@cpa`qU%CTx?`d%#?sT$UrnzG4NQ_hH^6Q?%0i857TQOFl zzX2hgq776~+Yr6-BaDd2%ks19X6`t*9+JHpTZfP(O{n(kDVcPpNRjp6*@w<h=+lgD zYX@E8U4!^dFAT;W2o5`Kj`*oRGK;!0vf;OyPShp~*o%DG!A-n*XM2YZ#&1(dp!<@s zlF*sbg{MN{GpmjBgC<$nCZ&U1&0>ZI4AFlZ$EqSmDCTO<v;3|DG4=XF$C4;(&dDB^ z2LE*tzY$}l$8Y$advs$<+r&p7Fy&fTSX-0!Ati&hv0F+@)zC1U1?@^pnAEeK7tiUh zsf{&wDpc+ruX@~lpyJlcBF@v~Cx%ocv@L649nSfd(A1Upr`q$%gV4bp_sQfg!l8pE z?P6W*b0v3?@iol*`N58AGY9!eU>l!cB#U*(OxrPN#HM9Umblvo_m1cP7FbNA|K%E@ z8*bUSN4HEjEALLCSFGlB3Dx2~w_xM~8KzM(v~(FO!^zfF`eVoAT$WdP;cY=66cG!q zUq!j;@#Mxz4GLAbo+K>sIIFr`!1YY;#VMVw4L<L~O3kyKXDEbd!T8ODCLla%(@*jQ z1Cn}-E|RLV!}y5UnR?17i)`ZV!{Qm-9*#WIJ)c_n{>!THt25W%_ZJm*8K)c|AJnia z&v-Y{+{N>i<X$lBW^vqib6fnIt;G#T!~EmR+-NtN<d>~{OB5^9&;HdtprJWOS()29 zldFF1gPL%eERiA5VEF6VIBfdGs){>sRulIDI^O&CRl~EsyvWJ{!4Va$QzXyb&KRE) zu4Bjy*D#0ooGf;V0nf+e;KNRpvvZBwz*t6x3g5SDS(c93g|%HOvR9Up>~eqAL~Kj` zxvXBbGR52H&pyoWj(5<T&WpTzx{o1Hk6r)DVO^{9;2)f2hFMIKABuiDsC&Nw<82SN zb*y6J!cDL7YWmUNZkkk{Bw~>F!m#!Z)Rcz_I$<HFoIcw!3QibhsXtrk4sf(|aQi8= zmSS4}zComyz~Pr|3rdt*>TLSP{lDGJ?Z`+OFWY=HNOYR9KYH3mY0ulzl%n0S>k(Z< zV%`Za;q#io-j8XTvv+Dnc94rV-Y+9$@%~_I*o2ISty5?=YM#q__}gzW$pPBn6NbMX z?L;=4tb!&h5Yb<*>U5-(I5$nbt;P<mk2qNsV^~6r#R&#fo!>8M$-DZLpZGMX$qmb| zyO7jzuBF&{*}C{_ryiB+Wt-7z`pZiF!b<1pH@c#+s9T;XZ%57n*p3U&u)|MmatW!< zFW-&;W5HcAC-RQ3)-SB7AkZ7!Gh)){|ANz+G|#ys%w*giu<&yT4xl64k3Ua~C)Y6K zqbHjVk7Ac^A8g*t(1VP|xJ`#Dram9D6WM3i5}0QfmjCn`u0aH;ZQ@2%(keX4vtjqQ zr}oO8bxPgRZyDYzwiHQDSfrT6c}=`O$Mv)zA2{wALlBDyAwmlPag7e)Bk08LlLe{D zEwylX?HW1%yE*x9O3&SLm4(+U4>~D_Ah^?6b-V6CKK?t3x&x+=YHOqCHj>PVJKMS| z^-z@#>)nDFbHA?ArWJ&*G&Og->DY3qN(e%VD`|(V;<k%HUEiB_Y)XSCbzt5Xjz)Ih zvn<&blF?nd=~Ap6+V6OcB>U3QFPjs_+oIj6Q8;>Qz~yywHtt?$b5es0=Cg3p=?M1b ziIXOvOSUJenw6L4*)DjOIc=^wr+jeW#_ohFfi$5<xl4KFI{!<tUCiNtQQ%zpmVRTh z@zd0CjndEFjE5DIH6NnZv~YgPYUk27oFca&{@|Ha>|f@4&h^cnq+rq#W)+J%I_0b< zwERG;G0-HU%gcGsqkYo$SL`xxlcu-xI*u;&9eUwtj^pB1GTcRfk`tAF?v(zroD*}2 zzOf~9?*=FD1VOZVN%NS#DcQBVk=Q=uFkazFX6X#x32-y83eJurXZ7I%-ymgvl|Kov zGgzPJW9#9&bseb4p7v{#V;`*7mNaJ>-f@jsIqrk9Wns{IXS!#HA?f6i-`g@A7-%)) zWnKgeb8|ghjK_BQTJL;QwG<^}#^Dv`j0Lx>HJbci(TFa*z5F{?qNJ*4^yAsYY6shw z3)Bi~nmfg<>6Yb}kkcA~(M%m>|Bi5_0NQ9yJJUyV^_TFPFZ%enl9`SW|K^F4V-XCZ zI@*{42I*qEiS1(z4uJcsYi~RQXMd9Y`If`o7`EK}!oc6F^Ot1x?Ze)WTALtTu98RW zHnE7{KKr@7LlKY5tF7O8v(I7kPL&R{B@W=Nrwg0*M(F)?(8&`<xLR5KIz&tBSWCJ= z!JU0lNlL{Fmqcf?zFXk|0rb|gU@tDdbhSFM@7oJO#*6FHPlxhxPCJ$QBUP2c^Vz>u zs`TOv<c6C5uJtb>2NPm15d=Jjqp7*<ETad}m0t#&i`O_9KGiyem`~ciWIo@rc*LfZ z<~y#j=5@`ZYnS%t>}y=4Xtr?-6bi-Arx3-01>?W_pis;Ot1IT>QI7BxlgLQru&?aa zTMAk#UKtDxsgS{&Ga%EG%PAgkuMD3jBzbnD(v6D)a<MK+oF3j0QF0labrhk9>XNk< z_jpUvyCa-@g9t3<?*ZpfWbxiaJ#!jb-z<>lY%xzeX@oJF-cZ{p`AG>7DPegE!(RjJ zHK$9UH|98c6HIjR@MZB1IL-hWS<ZzMN%Qn6dO;!r)Z9kbDRw{1&BZHQAbyteMssFv zx;bw{%0x=IWqu${fJzEro<;HzI+CUkDIX88c}&m6)h?1CT-rB30FjW<nVTie1JLwP zIaa^{5r?@>G)?{l@s@~<Ls=$>;Dk0Bb)~S^@)+ElJk8;ixgoj^5Fn1KFPz4AN)vIp zhC&+Pl^9HFA~}O(^l!Uzb>PIEP@pL=0_W155LlsI5Vj@T@$b#v5DUZ^$fCN0$n=yZ zFKaX+RBq&woft9%ahyQ86GnAH+EC?2O$$Lg@(!iU;ZXi*$3l=<0NPP#H7T>kahiO| z(mVl?Ej+6bXz~u-CuCFfl~~P^{m6P8P3G)HLMKid2Vg5j$%b)WOvTi_;c+2C$s0N3 zMdwB5BKZVYK9tapcs@x7_&gaX;II&bavMbSl$Lw+f>Jo7Dx%thGCE>k14DouHH>YD z8@RApya#5j96-UK5fzw|ao9Mzz)!9fV0FjW%^V~rBDrVbe3UQb!A~WvJtgCXsAsig zt6G3wyHE)If;8ofmTKrdYp)}@MI1^8GWdyFTyTy8upyBFNJVM#nA$|14ez9wAc-We zf;yTsyOnJC)1E1BaJKe9%=C$9XL!qE=m6SsB^5*k5HW~C%Q(>2(H!wm#zrIXAXzGs zpIFR<TllgCw52&*6=TAjmk9#0CAGf+fdmjk$;F?5yQt*Q0B?Y{s5+Gv2pMPnMAiZh z_!8ztCn6j>_>f`}E9BYhK+T`VkRmEliX)*&`8Nadl}Rkz0f}vF6_+SLRD{nZphX-n z1Q(lz3Sdsb+!ar*51f(+9YOh=mXnyECy+?&NZ6qOY?mX%@~?b@+aSfm{KN;uFhX85 z*UjpnTa^)JNZqmZp5zr0Cd|~4EKfEn(P;%k0oFzSBy~WwY3cjeq?ZZV`cQ7w(xq}s zu4S}69uN(Hh^|8jPOc+D;!H;VE|O62j6|$3EA7A>NqEP}Yc-ay&?Pl60C)w40;24c zN`~T#6U&JvU~!E=wybe_(YlCpZc{uNQ!NWt0%m~|{DxCBGaFe1-+M`GJ6~8tl-@U# z>u3G$S_GQoIL(UbfNYZMAli+lgqb2{p)_TyHn&3*L%<ZQ7&StXW`z23EP$dg<=O&? zq6W{11yFjRH$gC=l;G#2#kFn(0Zy}YI(o{JkJmooofj6!+XqMzlJO*ViWEVCx0b;M z1)7NzORh{S1TG*>yP`<&<NnN(g-jJ_W_4={jGui<;v@|kon$;k${uN_!94`}X>^Ge zQpn@skuN>c;Ws&2OC%le;VB46s3bN_HX<ZZawBQVH5neHX}+?D%ffqF2N1Fd2gFAq z(um@LGZ-~|3UWGH8hKo%6Kt9=CP;;FZ5K>Kv9MV@>v)(N(Ppq^Y|uxMm^|l!CZa8# z$#d6PAX*JzMu*r^EaMuXJEbzZo?=1gG8wt_xGGTWRxp*wqSvj{`|HA<5|0**z^xT2 zVe3Mk*P#!O&K6_Y4+AUgoVEtQhPEPt``o3NR;!ClpGdhJqy@Lc<-HB>@!o<{dU0~N zHg*}mzKh~ew&ul|S03xg5!sFp?7CR~`m51Nfd*$f;nyHcci)f58Kre^IPGt;qtX-k zFutHGVBY{oU%qr1D~n0Q4ieXw$RF<Is)tYYm7UD1k#KFnFHA*DeBYnsgC=r3n;tnB z4c@Kz=5uFoK)R(ZE`N1W7{%DYxFN^#)H3p3pK5ekq65xp^QYv_tH&@*S;Nvt?dLZ$ zRf)^?_HN0(*PBxfvByHq8MvsCGu>GS?jTAxHPw>>wj&=dE5$ZT!kT{J-*qN&^Sq|C znAFJ=N2=u`mGa>%lxdikVg}2H8sE+&1u8e5Nz}fc)Uh{h!?eUGd*yN*<B?Jndbu$7 zEtK@GN)tQRG!J^MdtmQR#4H#eWtIBUqe5fN=QrVfD~5S#9E?1&F+(T{eQ>5L^Yof> z&z8ex=EQCd8%JuEUy0lK3s-+tdF4jhlcrL0rf#4V9JSnbOvRhVp1HcB$uoSC?k1PJ zlY7bZ3G6nbe7lu;#HpA!EpHdjG|=}IWUKF2nW08cULT?)uiKKx{6ML8-prruYw)*= z;5v8&7nT2#7PY}09c^v9Usz8VNL<da2qS#%cx?unkbQA-eR=H7YV07gv3exn0Fhl^ z=9!jKGTcCob17HJ_@*Eyf{Aol<0*SHSznWDzxkbIF`3JyA4muIl=_V=N!Qx)U`Jvs zs{GUY!pXE9tpa&aPU`wEaj6^LOIejUc99n7t!o0ePoiD@4YT5~9O<lfvC>NKk(5T< zrsE+Kg-Nr5p$B;G2+p}pC8ZqexX1RaBsa%sj<9^wx?+z|!-fR1rQdB?(g%MmU#L>? zVsD%wv6^M_d1p)-rpd7nF=#&LYC-A^HFa(~W(n_I(y;TVXJeoB_jPBjdE-qaD0ZAo zyHeQPU~^fjm8GQZcnu0gyISNPcl_3(by{$wRP6%J`OUumEnu}Tbt0pH`m&bdK$OZv zYJNeuP=q?GIE(?;Gi<Wvx`st^{Wj0J!o%1PwU-FXb=h*543&JU)hiX>H{Ocev;T#H z5~=!hr}m$baU)nH{vJ9hR`0g_1?M%n`HOoBFePI@>TADYxpkA~W{5>gL+IkKLDzhn zH#9%>{@Sm0qZ{suzfNt7L-Z#0ZTl4ZafSIx4Aa!J?5nD)g+eh{qaX|6KG|!MpSY)n zCQdLy8?D!0spxc`MBXd%T|W~8{q)6YZ%Tbv3@BlD$xj-J9iGuVTTl{fyh!!s#W#no zG4|voK+0R`iVxO7__ftZx)`sSGe^Da|F{579)C8PAC&7^?HxKJ=D0Ks{vqA4lQ!+8 z3;VS%JMsM5jzsOfd5=pTC(;!Kfr13eio#p1?~&>Tc7|s%UTD_*(Kx(mEMk3{&UV4y zVIf%#m#-S?;!KWcvXVtV*ZT)42x+dFsjMbkY?m!DHR?=Zm8KFB5mR_f6n9?mY~s~T z>{u@Q#erI<FhD&f{<ZlomWs}yZn#BI-#SO+V3<XgyQ{sTq0ZEFoht(Nh_r(WwOl)I z^YI%kHtkYWY%^iHm_Ju^g@#V$#=r$4+%l!`x)(K$k@3pv@w>}&KfAuSR&9H0FlfH1 zzR;Q6-Sd~q>_bH~cMo%q9YYDzS6-?vP(?}-JRv7{MgDbg)C5XK{xKGP;>)pLvRtZZ z@!iBS%iR{39Zv~o1yWT*y@_)X)3;8TT$i2d+CZ&+e)w5Dza+fw`3TWdl>H$4O1Ovm zvzahORzfU32GWgi!=ec2AVimSxp)p}e{AV0svt%mD=eTugVx)=-d1?62j8D;xL1Bx zL}p5&>C(?3nZy)PteZvn2Nq}UWYE>>ULFH=KA<3e*GLPuaB1@bmk{=F`G#)h5M_Oo zD4I%6*>8^z#I{&6s)>P-btYfbAWi?Z9-uUr{mE;Ms~O9$az~Pr)$J=fIeNCds`#q7 zPZEwb=|u%eea+YQiWDez=`!T;(o7Q|pp(;j69!uTmapHENt+mBBEOT!cRAVH=Hm6w z^loZ47)T9&*E~QxiyYzgE*m@&A|SNykwoe`T5!0fit?sDaHdXs>*P!|V-;qsB}aCq zZ(}dDYY#$5x@N3>A*hU1RdYU2ssNtNO#gXp{DjPz>MbME61*$XPLR;?nOw(%cEYg* z_3n;1;&!Nf&|ecUD&pM$2;2HLgdr@82!*t)=V*-Y{ZxZLJ&SE8?KXOM*%oR0_8&;e zJ@M{-qL-EBiYCW%E3QPDxmA{<z3#2x6BTd|*fHm+s~EdzA65Hux@_b0(e3Yrr#*JL zmQ6W(*ij3{KW+BS&)c7{NyX*Z;rwWKT*9@|hRbwk59IWxk(Sevq}UzL5bDQPIjPuB zRr)qJz7ZWBuu=94BMBY1r@7wY@$_$yE_?=hc+dCHJ3}_UfLpXaz?HS7m$s3!)MLuX z35st3voHM1hR0Edn!ES=tr$q8=qXZomAmh!HigVRcW+Saz!E!ORMFVR8@*q9UBVbW z5oqKiCr*gi79NIKlOhKO1c|wDyR1p5?y;FlwB^k1Aw4|?^^CL3iY_pMba-;6vTV)Q zmcuWUj=r6UrKcJ1*wP=Kb*RDd<@kvJV_}ZWa;GEhhK0NU;yTW>C+^f6Tcrd@6Y6qf ztK2+|;1?O)qfFv>l2qktBX<vibav$(`<_)}7u8qzMCoOfA1mkQwj$c+*4)2(^`)<4 z8ozm}$w#Rl2iMfqvX;}txfF4XBanV}EMUji=Q7VpuVI#D;3`7S*P5#MAW{azR%@bQ zRd+u798z`a*q$JBz5Etl1X11yjO~JKE{<XCXafH3V&CD1u2nal^%kIoc}A9jb?XI# zy~)9Z)&sY%eL<u*9X9r_y~NVx)_agl(!tMq8N&7EWb$ZE)d~;B8g{PN9_4c;iU#F` zIZt!ys>F52OX2r3k2r$E-5yJ<>n*+gw#r^D9deaAIc$1~TZXU&)CnmAdXS9bU{1AO z_Z2uCSo22HraZ@p;yB4&)~&g4t@9Zq{<P6i@U+y!Hp**_U)}niJnPHB-3R!s52Y!z zLR?zQ>Tv1DAYO+G;(4BNe)IA~RPEUPY<J&Xr&Z@w;P*(#s*}t$=o*RN*UI#%TKyZZ zJ=JGkSJ^P$|EwPonCc9YT&@8A?PE7yRQ9x2yhz)SsoG+r{Y*B=@2j{}8&|cl-j4c9 zaPHEFoX?gNg6!2n#QUH7YEJ}GS8NKRG0R90XkAFEXz<6=(BNC!qB}+AaN_a1MM?93 z#>S<@rnW*LWzRsmWOO`P`rEkxwL<waA=8d@v83Zw*QzC(c#)@gt+}qW0YMC1b-pHH z(l)SA=CQps(nNH^%km(hgv5Jcmbz_iOtBZF8X-T%5fr;obxm=UE_=<{P^ArLTX$?V zB8(t6yA)RGm-t>;u9ot!`Dx-M_syBDr$$l^NYkai#@dq`?6*!n$SH9bjmGR~1QU{< z!U^wL$*5aIY)-l(4lx9+Ru4Vp{)$>gihq)(gy@<OQO*}4$DU{L1M;>-o1|<{dmYWK zIwt6{cSL;p;(VP~x+xoejg<Yj{;Wsyh*tQ+8=bjnKvF1}`u=m~YS#@x<@l>rd8L?; zi(Oob>S9HfR?`!{zgBgHg&y+y=c6iop>8qYzPG?|%Z`zY;8=E8#V1MXW%?wKV}muX z>|+2LXD0K``MXwaOzFGlGoW{;KKEoW{7%pofs|!lNXZ!ZPEg1e35x&rUxu_9{;vWG zv++1<fSpJJ=YXXs1lt#x4u|~R7z8MQYxx`eT7&(oJU}lz?m(_7*d=r%x4-%*o!=IO zuh2}3p=SyCbjk@hahp}(mQot%X`w18?W@z#a77kLp~H*WxE=u=5=6`qx5-#?x@7k} zUicfHgs`T>64>|g4x(NLKx`2afkAXUZmE7&3olF-MfRHm_>Blf_niJ5+z`Nw1ic;L zW(6+?b1+?{iJ}ic5-S4o{$jECfCK2y=t?HYILY`b0O?F;li8|SErnG&5?#YY935?* z<%c3+;Y8Bry7n-fn4Ko_yF+X*2)q`XAnxDv7DwU`iNQFgK9A#Mj#GBhOvIoq<yK;j zvjv>7ePN6VvjDC>z}n*oaIQ{rsebF_#3V)Unha?pn&(gnC#Uo*{zZ_dg_w@-BKnh- zWeJdNL$?abUP;#ch1NIHQQ$a<L}0;@&%!g%bRIq^n4t1oRlG6+k7FjV^MF`wIAKeK z^Svi{WXS>zje?ScZ#7RYuS9eNRrCgF31R_u9v47DjgNiHw55wn6XM{OgrQ0rf}00% z5)IRoJNbMU5}dTJ;mKKKmueZSA|g*J*YywnMMx7s67!1!6oQ#s!Qv1sa2wu2p$eWg z%p2U|J5|LSa%1rf#J+Zk76ezP)KNI+?Gerv_YsoNQS9(FX#W_gT@nj7Z*)0vu@Wvt zS(;KJMZlZVl@xC%)J6&>*n=myHi?wa9sCql^FVy1Ij^~Et<2V;o8In(#<5<)?}8lu z)`W0|Nf$R~G%0LyWjwt7@i5EdG)GG#X>FIH;no@?N^rspYlNd;6+nkH(@c<fx+&T3 zESwpW8yv)oTvH?^7VaoPCgKx)bC)8TWs5BeI7BRv0cXBCP1{?<$z>im6LzjtewLIW z6o*ZI;mH!@gD+d*iM@=F87+5$sRi&RlRFn+J?aj@;6R}r!vsgC5D=?g!~9q)L?z|% z<;XX*&JVL3wPAQ+OA#VaN~aPPR#2F14_%v-S0F&^uhfrS8s_Ef>#)6X0YDX=`r=?= zzJ2`{S2jdnjgYCrGzvs_CbvuAHCBT1?6P>A3D3S>2a-_Wu#d}Rn}ayGSpY9`hph^3 zxVeu*qCI4@a>krHd8t>*q>M=g_$p7~z9?Z81wixm%XoOhu0wzlLK`^@HJ7j?6y$HD z&IKe~KoDqdGo+&}&9-r2%B&mau%8qB(j0Ntu?(eUZra<;@Gn&Mz?OwKL=)3keN_~9 z*;L%*a>OD9!o}(1-O}?a%|*O2t<96%v&xv@E>@jVoSq$GKX(m}sROl2n#Vy48jouw zPTn>2X$WHBJlGA$0pIl&XcEzn{Y%=0j#_;qpG5CQv?J`O`*0k&7q%Q`My%rvQE=M^ zX2>lcUq*>1DFzt<YvxES8JpZh%Elomj5*3u2XYhIoXoTL0J^BkC`Co_HtwwYo=;+d zy1kYgd^4w6mP}CThK+`ZTu5l)?Qw$pYV-k9f5S8fL>C*TZCKVor!=Dp^}DPfOmqll zOK>2OXYEOY87}u;JXZXNLiWa^oG(vtm1FNSQkw#6tFpXHXlG_m4;(8M#_3tXuISBj zoL!J3Xljo3@NZ2@;z`3Ksq4^2$oD=Ba{L25GRs~c&=9DX_^u^(7hs34z7MM%?^##k zCVGuAa!{Ldh;WeGF9o=US$<IRI`<`s78i-qi@q0JCe0&eDy4LLi-`3Pe?<;DenygR zmZIZuKu^lsDX2LU?mhOPnW$aVQ@njQ6p(zm)RiWZg?z5`P&F_4Jmt`UL!tRG{9m`U z)ft{?cb0`B0Q;L)73ZuC)0ihO9YJ2``sNUH?$L>Q<z9!v@&J>JPo=Ljo9@;HZe9P| zd82F`oqFEONv^L+q*#3N9%S6{y9yUi_KqF;bAq4V-mB^sfGZAe<C9t{$)4?D%sDNi zIbE#Qc9G;KLko|lyiEY_oiA<m(3>5+m{`ZoFW&6YWzzv)jT$}7wkvSXHL^s*)T8z| zvmM3CSBaVaFHYD_al0ejwieovy^*!!aqH+esL%dB1%uWACV;6V>#I8OlmFkqGkgLz zY353e{tB|u>0tYp9nBN-^po4=-9<ijwxV|BEN+m!Z!VF!-s5>={&G(IrC)dMUosZ$ z(z6hfUiSagbtT|zZS6XdNP>_^tHvg%w2G3pTG|o`S_G{jAw@N&9+c8nog6hJlGb!8 zYV4??C_&NU=tKn7(w?KLt<qCL2b>O}hKM0|JOBUR=iGaryPjw7wf0(TuRW}__g>%k zz2Cd7*4?qqV7JshatCJ?ROL76s|2a&hR0WbnaJ*wp4wz&9&Ybei9`S#G`-!=S4<u_ zT|v?-j4ar)1l4E1kqe*vP?W;k-QM~1@XzBD9jHUpuXFoMgW@ZxHTSEJJF@Iv$Vxv< zE%KiX9Ype8z1QU-LS9Ho7961(TdleFaPo0$A_o4nGhU;fD9#rqiq0HG(4R8DEw}xt zXp1qdi|~I|ls$G}7`I}(uv4_&tumoF!{y5SZ6sg6jDbb1o<yWHm!pSq#^&3wMy@GN z#FHBeigp<A)-}Pu@`wnmn}J)#Z|eX`qF6N!+i~P7Os}klBT9KgcCXTfeOR)L&JK3n z^g*ay&Z@wGc1FgS!ho;Z_t8_4a3^6`=3AQiZl5QUykB;->^WF)?&!o<XM&34PpDBx zi)t%1pjO{-H=ud^suV$EIA96YCE%k?jdL!^gx?iz!zVi)d#81@&+Jlo>a$4@Zm^@z zI{CWC@&QCht(1^D)Of>-{(N9ep{&3v?R~-S@~EVJPG7)xCaAM76ZPPobz87Xq@;Z= zT#cWFr3iJ8^TN5^l;N$8=i)tk1OlaPCKg^q$lkmua@X(XWv&qqIUmVjkL9>ZZTrkZ z0DN&Il~ia4;XE{Z0Bsz^TltMWDnAPQVu3z0B46Hp*xFv58`PJ34dM+2Z<)O6Q{@>x zt5xsnm7gN$eOW~-pXRHX`vlnfUf6j-su8vrtCw5P6wW#;dd1CD>mAUd7941%4`Y3I z)$g}(CFnQWUcLF6tAD~p9Na$_CqQvaf=Y&I4M?pfqG`x#Snk}WIg;46R-F72`v|Q+ zE`Ilu#&Jf4sqC0WC0$W7%0S?p6QBQRlUv%ysY{#!#o6RaJ-8uH#`8X_ph9{F^L!4| z3*VYnyIb+TGUGu<1S;f=m1tcMD2da>6y_sg?OE|+0%vqA2C_AX?=ZV$Xq|H<JxJv# z{Ar^q7iBuHmdVp|MzhfrOq$4grbte_$o*2(c*Swj4-s<lFB`b#!~~^k_4@YM+@l3Y z=F4Gv-zvP3(F_-#Zon4Nj;XYwCF&{bG0u1uB^l2cp+6`RQZMqoPfz+?3RJT=_cA`b z=$wmUMui3SlEVulW}q!D)o5hbx}Nq}xCy7hD0Y+Dr5gJ_TRN*6X4a!zY1^6knOU-` zOZMSa8#>RI58@M@;HmO+=T&-Xkq787PyY}nG%zoic_6VWW~8*CRqmv_j&cvbkm!Xv z9n4`Ots~gN+#Co1$zw@>NYM(qkcS)N9%_f<5xUKlGTzcX9mO3XJ@uRL>Q^K=b`bZX za_7OE0DoD)QMjyywU?jy>ayqAHxHdf1OigQ{g#Eh(=S?Bg*4L3uyHX<2)uG{=AfWp zSp`_#?j_G@AbH=$Q(sxP;Ha^W)W*-}pEuh^_&I(x#bvky)3}R9u2B!qxb_o@$kdmR zX-V2sD}si*vt3M9Ww`2Yq>?fCy9w~3NAVa~Y$E!h4Go+}$hSX;<j32^kn=N4t_0bb zd)P>~`!$#vGGe94L?{i^2`%7db+WY}j67(hUw<1YHs8h#)_VzKhRMrN9B(X|zP-8B z#x-^C8JqdeH;>!~&EBccS^se2^q~FEJ$=QV?;h=E8cdxWoTxW2QQQ$mim<w}5!D$# z@R`i&OMA>u2}er)Om~B9jrlS$N1tx8hXz@+IZgF*a-n*%W8GDir0J*yD!WC^8K<Bx zY1AXC3?Lv&+KlAOR;+y^xGsE8_t$Ew4R+yD;Pr|b6V4~63q0r*B8t6UBb}_t*U+5o zZo8}@GlG1DoH5R;$}-OHbaA~}bqO82{@G@CNtm(<7#;8Lcw#E98wrZd#v_ttp<*rn z>20hNn$_yL)ip&Sn*gj{Zl$bl^F~X!NlXm5V>b6WT+<^2uzBvz`E?(z9QIe3M7PQ- z^&C+tq(?s>!aoYW1kWM%^b~^y%5l%*ImQdUpEsH@6OYWuzxT=oy=h^SZO?Jp%R-Zx zskolI*8L57#0bArvtvk+oU>u8nM4ZHJf4xN9G}Zx#+q(S@0b;Kkpy}?kW_zr@oN#T zW45YWAfNeU-CsIfjO`_M&irH+u<zjBpA>XM%1ZrC_68i<_M$H@Z~GC1g0iPsvb9eD zZCYaQV>7XXs2R*iv{p>q9sWSrb#wNsn*2)(AC*4YL}#Jbp)MWjawk-sk8ifoGjXoN zsD&GH)fc!8uQ_RbOF#LG#EX2^Mc{*}(s?Y!AL=<5>VkVLQss|Hd^Az;j+yy(H$Q>= zDZE&0(w^O=-Y!gZ!0vc*q1F77a%|YHl9})$=AI)e!*2MYPK*(TpO4(rDM)kig?Gvy z=_n%+4ke&RC6e<9#jaPzR>^{91YRu694aw5Ppe)K4jn6l$Ztx8hN<RLcVv~?V4mt6 z7Hb)R?!R@g*YCNT(f;TqNrI7*p=Ni=+-stK2K9hN=43?7w>$eV`&b`}RXkwsncsMg z&WAV^+=@X8J_E$ZO>b#T(NdrD?Y_zK&W6?<4ZchofYMA#Wq-L72e1=1nk&f=);o*i zhp}nzSFnUlBVaKg$NIS*9tyB+pC}sbFB6Wf^m%8`s{XQz*VE2j-*r=H1BY&=EeX$M zq-u#96Ycm|w8=w=q5k|k+UYl!UFWx-6HAVM6YLy)08BWS;9EO!yNao5p!rv*VXyu> z(<<W)k`+9}Q~!e&8S=E<H-TP#+?KsSa!aSYVn4ZF%hE!Y(DRKx=kYjv6j~QE7I&5M zs;GG%rg{0Hlhp7Q#m?W;2zC|<Bm3A=_Of2k&kG5<)WA)wm=$@Kd(nRUGt-PS=DUwf z%V-d3K6xy3pv}meoH}>aWpv69&$B%1I+3D7HGrf&HNv5?{K6B7F*jvKTmbyASv*^x zkk9P&U$748h&J(@VSldtHUB^fl;SHdLnI8Hp_R7xY8S6$La$?|J){OrKH_<qXAetT zQFxjz$jV9!#F|_oKDGobZEd5E-{K&~Qzgq19dl5h!@*6FcU~Bj%{g0bIqi5uxZd|` z8E9I%?2PG594AF37tu^z{3fz<oMp$f!xM}+#^*%nWE>}JEYXF*w0+morx-U$_knR^ zxCUF+ao7|Cgt#k{TkZ4(n8~6N2ea*{qK3{=T~gOsI7#e%cJ*VIt;))p;=t=~WW)cf zIFP?w4`G)!Na0gelHl*4l!pOE>=&~8=rpmO9o2{jR-zjl!Jq^N5lsXP{I)3?obYMq z9|5Wo6aua7u_Wvg>jVHGa|Tjs4<POBzKvv%m=p^bq@&M63Ewd$AxnM;N4$`g4<AC( z#wZPQu&IWHNA){kl4Z1GP7FuMT2;agFsg>p$bf_<qS5TpJNOJ$1R1Ke9!o`{v)WT} z%V3tCss<~ZyvQsPIM&DTM2LJFa}0Gw*ba5U7!&j}EE6jYcmO1yyDQj(u#8oJ5F!Kc z0BV7tub{w>#8+bg>ZRjQUIs`9S>x(GBT+>F(u@sixdkm~n3&k%-kF1hDT1s3a3i4* z8Gr!2r>YhS2MmO106#`9J`r#eu(3f<pbg7_?R8<5qMA>^B-VP6p9b0?6g$MK0BU2q zz6(aBy&Q()>WA4olUb4+B>_lw+XN9d{=L$7Y5Joy2i(<@Y<KbAOQ8g<or+=?fEd7) zo(HqK#`^$IJOg_%k|v2n!ogg?(;aG{j|M+VM7JNn8~X$(tDA!u1S|#$07Ia5eI6Vf zln~Q*9uF~vf&f$>lLCm;*IZzLMHVCuk`Ukmzzf3_<`alcD;Kh=#T*HM;TH<6B%Tnk zkZG|L4uCnhXwRan?f{Y9cc)bg7%mkYOISAG8W<TIo)I$<$W9hgLNI`A1x(=^IH;^N zp|Aw1aTMl5l)_Qm9FGKGT##~*WzNN3@b`G`_IahSc91?3LT;kl^L4`u(JE;|txEk< zC~gDb#mtr$t+G0X`Ft#jx+KH^&xTzGOt1<}FdYDP4B#RmVjZyfrHEu{?wgE)$c^&@ zkZ6{)5J2YxGwx-yMn;gb09TX*P}HT$YYfEl&uLR4^p1Kp1gJ~oOaORGQUU{spzl1< znlsJ<ITdiO(d3{y*|XHYZT<nuyX@(6fn0RBstPxUVe2F!!F)HDdJu9|`6Bx|K(VzM zEkZbW;EiF53jAnlCAysjFaj;NnF9(v*ega(Wvl7UKQY{fuO57yiu}G26T+~>kfCS* z$0EQ2G&2Z?vF}W*rW{QM0X{fF8&^y_q6H0-<fF-KRlgFmcz9aRAmla-0O`QYK{6w` zSmdz_@Q_dyBY_T+_f`^ejfwyT*jX|^KM+v1S?^#4k8bmT?<XTDpfPFf(QeYlVu4j+ zobD7b^pQp!6A<wDk+jg=4x^iZfeeKSM9K~3P>ubgPy?n5ZiOn%RYo&$v%sBx3eZEc zkuJC*Q-s5)gf}((QYBR>HXi^Ey%_~jd;<2S(&Zq_6tNn{wf!O9n2JP%0EQ8%aX1dK zJHtV&CSd1Rmv=4nR6>;)LrAm&Xgd=?Mv!3^ipu=+HX;dwg@%hcnT|R3vO4zIoZ^VN z<jYyIW6k=HJ*J&3CTe;W%+dj5{sf*9h$ChpiGbQjqJ{&;BcM&3HV0H2@G7hc;9Zdu zfD8m@ez1V`A;$oKz$LV?1BM`$aWy~^+%QK|i6H_;T+PE|B1{5b_28-|1|SR%33t(9 zMH!$GOz(ie92m#JZA@mJP<t*A)}w3;9xakfhTJq!ez1v+p-!)9+egJZklOD<SXOd5 z!jL}ATXIsFBEwl@AI@FYg-z_pE!P*lT33G1XcrhwSz;m|ry5JO>?|U3#i<V$`it&# zY(1Q+mJL5^$YSibz`4Hl>sUY1Sz?r6gGFW4Ms9HqxH|q=H)N_ndI||Ejl4N3Da2*7 z({|j_(@1}YDr<B5qbu`PyB-tPn+i&<aRR-VDiO~zD-A{tKw0}=;InV})mJ9lZDg0u zR$Xr603Zs*H-O6m@`)~cWcm3C2um`n2cM%`qZ90wf=SkDh<3#t&UORR{$I2)y`5#5 zVk>h_uJP3r!67^5g9QQ!r=VOD^K=jcZLC>N6p~<oj5HN<r#ORxN9$XyyY;dCJM^JQ zq_Ax(7NG>6WV`8a!AXBE7oI5~FNHkQ3oqQqX~p9zp^hWylsVz@6&qZ<*m^@`Il7Z& z3tDo~#cd9Eh7A9_ZVM!2ex?F(a!1f>&4#MsW8uJrVyCViB)5-t5OS&mtIJCB$8o^5 zW<dl44-e1j<kwlHC&!LCCG;5<HIUcapg7`KJ(LXANXcBEx<%;s6f%vk06W|HT;I&y zJXbbG3)h1?+56j?L#A^WyI~Jp3qCROk=6|jP_hq^Qufe~;ouA&ujsxxYFHiPzc56- z<b+*%JDd6N$y|wn$LOBm_~T{@TTj&t<*TZ}o6?c#znAJN=$bX+m6X|HzNt^35wBpg z{8cZj>%M@uLQn@kfCsz#jMRMG$n&l?J6CY@#%QyV`-?dopmx<cb{Bds@|Lh)0DcMY zc!pK$ZiOpcQ%(1|V`nyX=V@kBEnHIoBeLLx4xJMEoB?yAOBFbaoQCfTnNPH>e?XVn zKZd{N;xZt78e{9d*<q^LF9t)7lgq?VRe}*hj;VJYXhq|(&}}|Nu?9QW?N$zb-c%UO ztp1JjtM3c^?xM>CSQY(i;1<`v?&FLod7=Y&>_k4GiF7~c$5;O;mupwF+-w-0RQ0lO zbFt!$^8-+{r&<<E?w$P#66-qB*@EU;J|~^{ZO)Cefq9>OacdwCsscURsLQHW&wr+8 zS^*GUmWN2x<m`K1t7!xJw?ZGC*Tq)**kaZpzLrxj`?zFSbxob3DE}TRs8kVmTnlkx zLz6NApGrdy2W*C0VLCq5m8o1}=6r)Pm>gIcS9{Tb9A7C~elZn>ChA=_%1M%4v9v`O zq$i`>p^wT|F@C<fxI4DyEpO6XDwA;tN?LS=p><rP);>j_F=ja+d|36e#$o{7J97`Z z`<%G8EAkPCt+eBIY{SukREu6VR~<J=pk#bsxO(N?3(2xydLbHQ{m>rMeFM`}2UQrI z!-{o1hR+;*#Y-?!xQhv{Csnc0cU`wL-*>j`J4>~TQsdnO_1M7jZb3?*k7%h@%TH!d zW*0c-#T6LGh!2;P?`7_VO-$ry`E%<8ls=L(;5y|ogV;2{`IC{v8I@%B0VG#KkxIhF zy*|N5cMoiA$UE`fbp_BiEbp#sr}`DOt3iO*ubvdpel+K8F~_0~TVTAm9PAI8lSA2k zx;<*HDxFOp`k(85Bkj6i{!2x7pIsND;}aAQMxG`0eL=%>HM0x0VAax&ZcN_7AWN{m zpBB6eQ>*MFK1MKY-k+PB`E-e*1`*_<wB!r+XqjbIjv5*+=oVLF98VNwd#M%hXxR_d zpdiNn9^%6M*WteUyogwPG#kNu!qJ9}HRu~OkKEzq4NP{6(}#8c*o<qo#vWOw@RJ9v z4zs$-&#dYi?lmi=)SwI0<{qiPO8pg;y|M;DtM<*%?pyR%Jw4_hOBtB#Se}?ovg&9s zzGqkvA~}4`?IjT++k`U4Vl(hJ=iJjHhs0u{dOOJV5BziK2MP?8w>9KzXsh{QV@Z;{ zs81<m-qe$40z-qH$gM_G2a|Sg%CULFEjP42Z}+LbZrz80-%eUZZ`=%5P!w!9382yF zvrZT%zMe35FGfR2Rm{!PKpmTEPF-iXGi=!J$>1WvL9*z-No*4c@0S3OYIwv-o#gG~ z?&lf!j)9N&_qMscHl6QVreMn~t~xez6Bi>bC-cZX!4ql}BE+Dt0rRyls8c>fo4q;x zHH@I^`<*PEtk4ePH5w>|Ne%#ZfTPsHH0B#pb=S=oQfZ0;Vitt}FX@ZmS0Lxc<z-$- zYX+cDd5E^xl4_kU-9euC%byi~c9<1$^-`(RtyWMwZU~7>AA#wG?C&8fkyft7R6V?1 zl;QBo(%FY-AvV0d2fN};C%!XbX^ytY>e<@c6zP&PCE!$v^uW7UZl>Xh*W&svob+cZ zzqVKQ*bnRTwwLS<%*yMM+uZTs4h4;ok<P`8gg<d6Zf{yevBWN@`UJPv<Q3{OxCKqK z+{Zdzz+OcF&>oRO-eaef@B=@T4!3_6&Yb+*&)JY+=<$Jh>5<1GVWmzJg%Lg9NS^W< zn>gC0XuY-V<LA&{w)dZlW+o1AY7m=r@|09}PEVEok@l<zl{SR)l4p;Vm4YP6c;haY zI4!_9_Q(u;6i^~Wxx&IJ5_tJy%FDZ>pXT;3Nf=t=K1imMh`#(FHa_r*^uWRQCN54> z%EF;GUjA}i;NVIZYXS#qe=~$brL{|c#W&`yBHY85@2-bzZEcOdPk+ngf!)-c5v)HC z=6xg`&)1S|tH40<A<gV8@3MhZt-=6A@WDfO>l<=MeyLjmr|t3!b8*UGKX`Jb>dKx{ zOWTO#C;7@rGRJZL3Dn9o?&($3=&813h3eJTh1{ZQA0v~{29txkT87TJrh}!wb%dsB zW!rkQBp#}qtk&x#y7Q4i-@*2^_$B?&d)Hr|b!xm9*OB9`qy#Ux9>Dza<UBlWybbZ( z)S0MgO2XQi|G-TrTl$sfEb4FVY`iXApbtzgak~8H`o9I>21+~jvCa~~Y{i@tOa88p zAaB>DE7<Qp>f&^_)Q4A}c-<DRscGuUe+SpJGDrpskjdRxOsB1dw6I3Yj&hM+*niSM z|JNt;=??w#>ny?Jb(IH|8-|XptHj-{YCnjqH>}1MqIk@x?{lf2$Oo?d{DnHuqg*B! zhHab8+)g3I$_J6Kf+S;OZjg~(C<&{ezsEEYXF4=}4AmVX9q||1^yy&+M@(A$Y`m<| zj&X18=<3}9kwOk_(O73HzosZ-f5*ttbD4rZt`Vvo>dZ)LO+6@WH8saLjG`t<0}x?) z;GiL3p^-bog!|0^aPXZ%^1YKsEa2_(Lao|aJ@626&pb2kl7o6%?PANd<n98<hAFR= z-z?+pAXkiv0DIJ%K3O5&eY0B2ch&1ShzWFqV}rp(t$X!*uZqPa`NCwBIb1<I#;GHB z@s20B4x$#^b{6b*rO(^4KRzkY!s5_XGPQtiXsJ3R;J^pfAo&MyzZ}ZlNfQj#01mg6 zYL8|gaaJ|(Fz`93!Nf}0jmRyy><1c%o~szIiZKB$)%ZeW$&WyQQN`3j7-pbEjvdwC z`u4*kVSQh=Q8HA$Pr}5bvW$y9`cF%(QGl7cGNH-{_9420pejqfY>mr;Pja!4v^lGz zqmL92+e5a#Tz17kV^L9*cJs24=^Dr=gq7jybbSE~Pr(?;JRCWnx-(pJQEAHy?Z4Iv z+7a<rP-$ck=^zqu>7qsVR32a+d>#1K^EAPU7Uz6W`I!YZpgS(1yx0<!zpN#5DcGrv zpcfdK>m5VEgXtVWcPiin!(N|^Ka}B6HpQ9g7rldetQbq}1lw?_m40`F4<|7kApBnf zv-y*z3Les=%+`?~lW8)30)8_@9J!OaSRRK|xcgQRz32PiN(ITz|6ij3l)Q{R)?SZ# zv6U`Ofe#pPj4gbLwRDoyAki7q-crUyL}qn2ChT1xw9YDk3jjWc-)mZQc<p=#Ok>J~ z9Si~}fRwk(1%hgDb6*tgdy-e1Y5DlQPxrz4{SbhlnVrRMY)K5n^VqFKb1ImxV`o8= zoUcp<zh^^rNBGZqt4Bx8TJHIk^ySS=kCpHLp@CaN`2)`Esx0j>2@)hEQHgvZ;Mon% z7f{iT8FLPQfz$eu@tUll*c_W-r>>5N<zvo7O?gD6JwhKRVFfB9z$`4jy7+|=nw<|( z$dY?0qo8)o<XXQ<qiRUkd*92%z<sQ48|A%$L|h^|4UkA0TTrQ5gfFe&XBgugA|@<H zzhA7TsK!Bj{CXOT1h2xNJH!l2RU0B8ASW7tzc145sYG1SvU912y*b8d6;ta47P&Al zIu_VF19R#r$2QFjLLBl$HHNJOkYXv|r#kCcvGVr-?wX9$1tWFO3Dca!H_fR=CO?8H z<*~ZZ1~UlRarTW65R&EgI{agm%lZJ`#Ti2;A#Y9F^F0(mGC-;(NsOJQmX)`E@Y>6g zrYr$cbRqCPt)yVcX@br*_kRUWp9|+>V87%zX@NEUb8mMkU7Cm=(Nqds1gi*Q&w$Jz z`h<LNk9d`&25ZG~EqKk`efHW3O+kozM+Zy+U5=UwRF`NY&`4}?#;}z+@enKwAPb?T zdcat*xk$7Pep&ZDgoT^lW}m~tYiedNgg0@^=vL%jpGqtSeCj(Wp%v0jGJywu5Do4E zXaxys8NNNxda_(l$Lnr`6;lO8_F~UOfSozP#s?81mz}-qc+LQt<k-ek07G?zLB<dO zGeDBqO&9Unm1PO2)b+RwlL4;c{>5oy3L;F*L_v4Vh*^RAR^}K&xJR&r!8KCg8bCnd zImB>a-%<(L!bcfZ4Vy5K0$$|zG$y18n;;Rf5{jJ5o<7y~a+ZRFA~Ro^;7qZc@Fj7d zfs%s#?V<ocf3%|>1$nn1T5mz4LA7bi$wc3L91JwjjpG;tppjH(d%%ir58K#-j;uU7 zVTV(4m<H_Pr_a!hOHMMstUv0b>^(xQI?P<^nI@-n3q{+LE|Lm2C2R6J0Ta5kO{E|s z#q($Ky^^9=P$Xb~*Odj@;ePQvnS^PtD@eT%0I0QK%M{knDxEAFq%uA-O=MqU`W``6 zBr~_4V~FSk941Yy1F&o4XDFA}pAW<*uc<@uN(u)jtX7GNm>ia!T%^v-#}_4=QjboX z-Cxz@jLH|}OLVRJYrE+b@rvC`a9QnJy4ybK#WsnoqI~j_TdzCm#~1nYUB58?tlRRP z76opzZ1cL)XBf?>YW`fW?T%|yqx7fj=wscDv+-|1Qb#0q63!cYmzil)6*oRa>!p5; z`Ed<Xz1W1FlVeFueyP(hZGyb5tV_yR!u{#8jjuaH$JRx*=ZnACDeem>e*G5Wav6Gn z+hl7NuIk}!x~jo}JC&){hY>9fT_~D5Kz7&pb){9jVm;ah=H@*gzEO(;XAU#$_*oaI zkRPi&*Mh;agbwVs6RVAtr)u{$fif%a<@kKoSv(QhY|Oe{kj98o@TK66D;G3<gFnxH z`zks*vcWr>PPJZb+{oE_LG9l95YV47H^S8qIoLaF>Z~!vS)~&4TKWpQ!tCh<vtN!! z^WOf+|G>)ZaM9oKWhJ-btV5sr=v_+IE2cr?u(CG_&UwyAx~ets)%5~zOXZ)JB|)tm zRo4ALi<eWHjhEA(NSS`ZT)(SyUjaWi?<>1>bTGS8t4^>SDCCd<K3m_x^6GJ1s|Ba6 z`mt$>ymwd@@LJ`!F$ZMPU0L4t!ZVvqeki(X+@+c$sf=R#PNBpDxxD^a2>z+Jqim>I zKi_WTpvlVbVzD|{%-4kdWm%Ok@DzYsbtC2zRW}z$9R7JoZ$q`vJIE_OOB|2ns_$#^ zKXS+<x!#&3G_V{WLS%gNY5PRxZm119PrO(n(N$#FtXG)wZ=DLBUtf50JX&|d%<ZC& zup>KS_aB1H4>x(6SqAW9{glfhT+Pl!L0Dsv$W~n0@U&#IEY&N%xlrI^8(njdo*(z_ zCyXiTFMxn-JqOP4O2-V9LzZ{@1XmPHHGJbWY#aE>19j`Tvu9ybl$)#6CnjyhzT{DT zRF1mADGGq>x_`I)i)qxOotAAXS$^2Ufy`CEfZDbxTC!<$^Y_cRc8Tfc4dWX;!5%83 ztK~jOx=?3<Ej&|J>@9mInyHt%plN>yeqbiH(-+C%?8qh)4Hb9P6`}WQn;MOip3x_o zQkCP%U+g0<{?tn#x$kRHv!Lqt_k|S*rO*^W@gyB^kr!1()_0*+IHLI>+;XztQ2eFO z#!J`DGsdHgQ&p?Le#l?jH_$Y#zMyrh?lgVpZ9iYf%~?Ep*~?~O;lj?ZW6kX?e){R_ z8ggjqAffS(h*Y$7+l?C*1BI0+!L<m(dmmlkxK>(T&$rZy%6j61@W%9MJ2qEi|B!OH z==Nq=WlxG_zG_c@=!nlqK~Wb5OykQ4br;gNEbq4d5miRRpr#*2`_afh90rHZxEy{q zlCjsC_U%*JGlfQtrV2`tEbS)eIm~-x<>EHK7!TBIy6=cw2kNn``hjzy)Qlfxm+Mm+ zw!`wXj>U;0F7(_5$IN`v&igf|E*j4@ztY^i=$Ud^77MsoCBpjSR85Z16Q2<L{7iii zsm_HrQZhm?YT9V^YM(mz1-1EI)VE!Xn&Z!2gX#6095cyV_1Qzx+S-UCA++YV!N-<c zw#TqFom?RAA!kl~y5IB8_dRD+xHFRN3$5rkT3*Os*%^8IS=!Ccr;@~BJBaG;KgYLi z@lC+(bm|cGDJQ>s>{N`s`}!>|?c)Lzv`GI9ruHYfXsk`5hAPI9oAuyBYOai=Z=g$< z+$NgRrmqp#W-XjA=1-lmdeuN^u}90lNQTE}Ti*F5IciylYP8|jp5HH)wyv&2uTCcu zmo`oPq3u(OpDCR<?EONr(wwF9n(TvARG}$YxRO(Uf9ZaFD>2}`TGC;+OJtAgoB7iO zJxFvJ8g51a=EN3oT$lq$a$~XDW00V1-0RZY`X=pHlbaQ>r!M>B;HYWCihNVo*?X*8 za&{pkVR+-K=;lAaw{P`vSo$^FiPK+UgS1|u<z3i{N*iI^+v#v|<dOwVg(G2XV|CR> zDGTp*1TWuxkF9vCLB?Nvo8a@?OL0YuHB4`dqQ8f&#X`PE@SU!9wnq&q4h0c=?~j1I z3iMEJob0{7M}Fy0qQ4=3_tR6<kI#%R680Fjx!ufZx}}HuA=@MU;mR7E%pLvGHp9F% zKg@ivsl9h2<u<#rgs`1DOnAQB0{C%_?TE=9a?x=vOPbGr9oaZnBNeObZ*9Ze8aKV8 z|2*FYttOXC-o|7Pk7!m5A!??M{bkY%U!4tAr4C)w2+8;`-PT0z_;S6xmY~l*XOK_} z&}sNJj(;M%hq!}f#0%wJ(bL34mkASgCc8_jTmn7)YnQ4j+YNa5+m?vf*HM2+<9;s_ zTG~hxi8rNo*qMRM-%d5#DF)ZFg4{MTT{3CDM#RaupBBH%gkc4mra$TH4hRSdRr-bs z`i8tRict1c7j>D|zzA8@4eNPZMfMvyPBppt0*c(lnUDK<M8mQsR`sz;y|&8E2UQXk z@%Hhs)tO_<1r^>~LgOlb6Cpin&9g&~|CC3)_d?|M4s8&%aktGQcst9DZ+O!05Yu_# zK|UE*K2RD!{o~H(ms?!;Az~3YW{#xe?(cj3VnI90&n#W*waEgPE3Fgl+}b*Lp;RSq z{Z|d2!=CWxj``Z_l$wpgwRVGxb)81sQ}-!&Z#$NlT$UV&^m#KDMah3KRI#vUcJMK( zf0yA$54&rjLeYv>!{_BEl7!bvk#io}xH~V8Sm@n?9H+n{;}bV=&YTx^*sCrC><+tz zb$dLww_zAEWHWPs?N_PVTql>xd<wR1EYcL`SA!q)1y`h*?RN#te0&i&_M1}5p-bpb zNrz9n=m<|hjSB9(cyWd`_GN`4I;MFEHtxm_D^M)f-3IUZW)h_15sQt|XRwOtb$-~c zE3&#dF2A>n)MHH807t!nX#A%C_U!K2hZJfr<kewax94u1=8}m=W(+-IW=Ff3tsKtz zG;tp{Uef1)@#Y{lO;7%ETK8t|SC?AP-*-*<<tH4m5sqH!Zxa(fX2NDZ9OoCgmBGw# z?1rsP4gke<bV}Fw!`I!HKlC_ar|z*TPK@h6c?ip^-saUpc)O|_uzqYmrohB}004o( z=iPBTjhCGx_W3&ob(%(GWz>4~3x*nmh9=*9FswoIcGD^I;O4jHr5;NV`Sy<i;g8D3 zpZU~2sI?-f_N`>Jobx4B=fF@uMx6I_8QSr6^=?U*v>+E7q$}5H<;4-?1fRJ}C55Cr z$IJ~*HUsPyPfveAVMvQ*!l<~R3a3qz+8C$d)t{elSUlIAf?l^Jbia_Y00KeWqhn&? zK_F06bbNRy5dR}UCV-76ATS`N{Ui5(ZU6=UqYwll{j=`>O)CIdS`jg!r`L+mEEWq6 zIs}M$t8(CPfkAPnf{p{(0ddFwJ{Qzloqvb_9OcP>GX6XMPsx8W{?|4M$Oo^jB)|d! zuSADN1OW;C=+OUty&x=*52JOi)dOt{4~;tYcM4d=M}&s`C%qQ?0NXLnK_^0^!q)15 zE2AS$90L;T<D>s>^q;3-6#B0+z0gx(YjxJbS~>E}sVMz_rNQB+<AS4rbm!@~)Bov& zwK|Q!Zxh!#XD$4*&3|P8zcc_j1Ie{zE&QJv|H}TyT1yVxW>8?*>3`jR2ypw|f!&}$ zY^SfjRuQ5~T8k8coNYjh^+228ri^v}Y8<Q&>b#H+np1{ifq5zje8(*)K4jNU^PRiQ z2{2#}@ZX(#Ixg<-&IOuTJ0sY?<MqI`{WE{9Ob^Hd8u~k|ZU1vI1IiNqUA7hh?cgjx zAoZKTuqgqSJ-|W(fmGQ*nepkkkeGkhT|1r`P}d&>BCLWy<QpK6=O73a3|tO~aV9h_ z2#D#?VSmSKyBPelqk+M3DkwH~tuOvNm_|gM2L4qE+Ef)6vvv?&;MbLFjeyr`0C(UR La0hm5Hz)iTR0fwW diff --git a/content/media/test/test_media_sniffer.html b/content/media/test/test_media_sniffer.html deleted file mode 100644 index f2e58055d008..000000000000 --- a/content/media/test/test_media_sniffer.html +++ /dev/null @@ -1,70 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> - <title>Media test: mozStopDownload - - - - - - - - - - -
    -
    -
    - - diff --git a/netwerk/mime/nsMimeTypes.h b/netwerk/mime/nsMimeTypes.h index 05f9c08d2244..b09ce10fdc19 100644 --- a/netwerk/mime/nsMimeTypes.h +++ b/netwerk/mime/nsMimeTypes.h @@ -75,7 +75,6 @@ #define AUDIO_OGG "audio/ogg" #define AUDIO_WAV "audio/x-wav" #define AUDIO_WEBM "audio/webm" -#define AUDIO_MP3 "audio/mpeg" #define BINARY_OCTET_STREAM "binary/octet-stream" diff --git a/toolkit/components/Makefile.in b/toolkit/components/Makefile.in index 95533a69bc5c..3e823257ee3c 100644 --- a/toolkit/components/Makefile.in +++ b/toolkit/components/Makefile.in @@ -27,7 +27,6 @@ PARALLEL_DIRS += \ filepicker \ find \ intl \ - mediasniffer \ microformats \ osfile \ parentalcontrols \ diff --git a/toolkit/components/mediasniffer/Makefile.in b/toolkit/components/mediasniffer/Makefile.in deleted file mode 100644 index 738ba006da8c..000000000000 --- a/toolkit/components/mediasniffer/Makefile.in +++ /dev/null @@ -1,30 +0,0 @@ -# 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/. - -DEPTH = ../../.. -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ - -include $(DEPTH)/config/autoconf.mk - -MODULE = mediasniffer -LIBRARY_NAME = mediasniffer -LIBXUL_LIBRARY = 1 -EXPORT_LIBRARY = 1 -MODULE_NAME = nsMediaSnifferModule -IS_COMPONENT = 1 - - -CPPSRCS = \ - nsMediaSniffer.cpp \ - nsMediaSnifferModule.cpp \ - $(NULL) - -EXPORTS = \ - nsMediaSniffer.h \ - $(NULL) - -include $(topsrcdir)/config/config.mk -include $(topsrcdir)/config/rules.mk diff --git a/toolkit/components/mediasniffer/nsMediaSniffer.cpp b/toolkit/components/mediasniffer/nsMediaSniffer.cpp deleted file mode 100644 index 7b8c177760ed..000000000000 --- a/toolkit/components/mediasniffer/nsMediaSniffer.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 tw=80 et cindent: */ -/* 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/. */ - -#include "nsMediaSniffer.h" -#include "nsMemory.h" -#include "nsIHttpChannel.h" -#include "nsAString.h" -#include "nsMimeTypes.h" -#include "mozilla/ModuleUtils.h" - -#include "nsIClassInfoImpl.h" - -// The minimum number of bytes that are needed to attempt to sniff an mp4 file. -static const unsigned MP4_MIN_BYTES_COUNT = 12; -// The maximum number of bytes to consider when attempting to sniff a file. -static const PRUint32 MAX_BYTES_SNIFFED = 512; - -NS_IMPL_CLASSINFO(nsMediaSniffer, NULL, 0, NS_MEDIA_SNIFFER_CID) -NS_IMPL_ISUPPORTS1(nsMediaSniffer, nsIContentSniffer) - -nsMediaSniffer::nsMediaSnifferEntry nsMediaSniffer::sSnifferEntries[] = { - // The string OggS, followed by the null byte. - PATTERN_ENTRY("\xFF\xFF\xFF\xFF\xFF", "OggS", APPLICATION_OGG), - // The string RIFF, followed by four bytes, followed by the string WAVE - PATTERN_ENTRY("\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF", "RIFF\x00\x00\x00\x00WAVE", AUDIO_WAV), - // WebM - PATTERN_ENTRY("\xFF\xFF\xFF\xFF", "\x1A\x45\xDF\xA3", VIDEO_WEBM), - // mp3 without ID3 tags. - PATTERN_ENTRY("\xFF\xFB", "\xFF\xFA", AUDIO_MP3), - // mp3 with ID3 tags, the string "ID3". - PATTERN_ENTRY("\xFF\xFF\xFF", "ID3", AUDIO_MP3) -}; - -// This function implements mp4 sniffing algorithm, described at -// http://mimesniff.spec.whatwg.org/#signature-for-mp4 -static bool MatchesMP4(const PRUint8* aData, const PRUint32 aLength) -{ - if (aLength <= MP4_MIN_BYTES_COUNT) { - return false; - } - // Conversion from big endian to host byte order. - PRUint32 boxSize = (PRUint32)(aData[3] | aData[2] << 8 | aData[1] << 16 | aData[0] << 24); - - // Boxsize should be evenly divisible by 4. - if (boxSize % 4 || aLength < boxSize) { - return false; - } - // The string "ftyp". - if (aData[4] != 0x66 || - aData[5] != 0x74 || - aData[6] != 0x79 || - aData[7] != 0x70) { - return false; - } - for (PRUint32 i = 2; i <= boxSize / 4 - 1 ; i++) { - if (i == 3) { - continue; - } - // The string "mp4". - if (aData[4*i] == 0x6D && - aData[4*i+1] == 0x70 && - aData[4*i+2] == 0x34) { - return true; - } - } - return false; -} - -NS_IMETHODIMP -nsMediaSniffer::GetMIMETypeFromContent(nsIRequest* aRequest, - const PRUint8* aData, - const PRUint32 aLength, - nsACString& aSniffedType) -{ - const PRUint32 clampedLength = NS_MIN(aLength, MAX_BYTES_SNIFFED); - - for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(sSnifferEntries); ++i) { - const nsMediaSnifferEntry& currentEntry = sSnifferEntries[i]; - if (clampedLength < currentEntry.mLength || currentEntry.mLength == 0) { - continue; - } - bool matched = true; - for (PRUint32 j = 0; j < currentEntry.mLength; ++j) { - if ((currentEntry.mMask[j] & aData[j]) != currentEntry.mPattern[j]) { - matched = false; - break; - } - } - if (matched) { - aSniffedType.AssignASCII(currentEntry.mContentType); - return NS_OK; - } - } - - if (MatchesMP4(aData, clampedLength)) { - aSniffedType.AssignLiteral(VIDEO_MP4); - return NS_OK; - } - - // Could not sniff the media type, we are required to set it to - // application/octet-stream. - aSniffedType.AssignLiteral(APPLICATION_OCTET_STREAM); - return NS_ERROR_NOT_AVAILABLE; -} diff --git a/toolkit/components/mediasniffer/nsMediaSniffer.h b/toolkit/components/mediasniffer/nsMediaSniffer.h deleted file mode 100644 index 4d8a91911531..000000000000 --- a/toolkit/components/mediasniffer/nsMediaSniffer.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 tw=80 et cindent: */ -/* 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/. */ - - -#include "nsIModule.h" -#include "nsIFactory.h" - -#include "nsIComponentManager.h" -#include "nsIComponentRegistrar.h" -#include "nsIContentSniffer.h" - -// ed905ba3-c656-480e-934e-6bc35bd36aff -#define NS_MEDIA_SNIFFER_CID \ -{0x3fdd6c28, 0x5b87, 0x4e3e, \ -{0x8b, 0x57, 0x8e, 0x83, 0xc2, 0x3c, 0x1a, 0x6d}} - -#define NS_MEDIA_SNIFFER_CONTRACTID "@mozilla.org/media/sniffer;1" - -class nsMediaSniffer : public nsIContentSniffer -{ - public: - NS_DECL_ISUPPORTS - NS_DECL_NSICONTENTSNIFFER - protected: - ~nsMediaSniffer() {}; - -#define PATTERN_ENTRY(mask, pattern, contentType) \ - {(const PRUint8*)mask, (const PRUint8*)pattern, sizeof(mask) - 1, contentType} - - struct nsMediaSnifferEntry { - const PRUint8* mMask; - const PRUint8* mPattern; - const PRUint32 mLength; - const char* mContentType; - }; - - static nsMediaSnifferEntry sSnifferEntries[]; -}; diff --git a/toolkit/components/mediasniffer/nsMediaSnifferModule.cpp b/toolkit/components/mediasniffer/nsMediaSnifferModule.cpp deleted file mode 100644 index b8dcf5d1e4c9..000000000000 --- a/toolkit/components/mediasniffer/nsMediaSnifferModule.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* 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/. */ - -#include "mozilla/ModuleUtils.h" - -#include "nsMediaSniffer.h" - -NS_GENERIC_FACTORY_CONSTRUCTOR(nsMediaSniffer) - -NS_DEFINE_NAMED_CID(NS_MEDIA_SNIFFER_CID); - -static const mozilla::Module::CIDEntry kMediaSnifferCIDs[] = { - { &kNS_MEDIA_SNIFFER_CID, false, NULL, nsMediaSnifferConstructor }, - { NULL } -}; - -static const mozilla::Module::ContractIDEntry kMediaSnifferContracts[] = { - { NS_MEDIA_SNIFFER_CONTRACTID, &kNS_MEDIA_SNIFFER_CID }, - { NULL } -}; - -static const mozilla::Module::CategoryEntry kMediaSnifferCategories[] = { - { "content-sniffing-services", NS_MEDIA_SNIFFER_CONTRACTID, NS_MEDIA_SNIFFER_CONTRACTID}, - { "net-content-sniffers", NS_MEDIA_SNIFFER_CONTRACTID, NS_MEDIA_SNIFFER_CONTRACTID}, - { NULL } -}; - -static const mozilla::Module kMediaSnifferModule = { - mozilla::Module::kVersion, - kMediaSnifferCIDs, - kMediaSnifferContracts, - kMediaSnifferCategories -}; - -NSMODULE_DEFN(nsMediaSnifferModule) = &kMediaSnifferModule; diff --git a/toolkit/library/Makefile.in b/toolkit/library/Makefile.in index 269e69b2e3a4..cd20833348b2 100644 --- a/toolkit/library/Makefile.in +++ b/toolkit/library/Makefile.in @@ -142,7 +142,6 @@ COMPONENT_LIBS += \ htmlpars \ identity \ imglib2 \ - mediasniffer \ gkgfx \ gklayout \ docshell \ diff --git a/toolkit/library/nsStaticXULComponents.cpp b/toolkit/library/nsStaticXULComponents.cpp index 968958dc2083..dea1e1e9def7 100644 --- a/toolkit/library/nsStaticXULComponents.cpp +++ b/toolkit/library/nsStaticXULComponents.cpp @@ -180,7 +180,6 @@ MODULE(nsWindowDataSourceModule) \ MODULE(nsParserModule) \ MODULE(nsImageLib2Module) \ - MODULE(nsMediaSnifferModule) \ MODULE(nsGfxModule) \ PROFILER_MODULE \ WIDGET_MODULES \ From 5720b6585dff48ce7a20d2907621b258015cbfb6 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas <21@vingtetun.org> Date: Tue, 7 Aug 2012 16:52:23 +0200 Subject: [PATCH 161/169] Bug 780336 - BrowserElementScrolling cosumes 7% of profile time on gaia homescreen, but isn't used. r=cjones --- dom/browser-element/BrowserElementScrolling.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/dom/browser-element/BrowserElementScrolling.js b/dom/browser-element/BrowserElementScrolling.js index c17f27daddaa..10286c4ed82b 100644 --- a/dom/browser-element/BrowserElementScrolling.js +++ b/dom/browser-element/BrowserElementScrolling.js @@ -147,7 +147,11 @@ const ContentPanning = { // root scrollable frame, so don't use our synchronous fallback. return [null, null]; - return [nodeContent, this._generateCallback(nodeContent)]; + if (nodeContent.scrollMaxX || nodeContent.scrollMaxY) { + return [nodeContent, this._generateCallback(nodeContent)]; + } + + return [null, null]; }, _generateCallback: function cp_generateCallback(content) { From 3adf3358230c2d6e240920c33134dd4fe5ddef1b Mon Sep 17 00:00:00 2001 From: Mark Cote Date: Thu, 2 Aug 2012 14:45:26 -0400 Subject: [PATCH 162/169] Bug 777331 Clarified some comments in devicemanager. r=wlach --HG-- extra : rebase_source : 4a448dedbf028fff07882a5f257770e5063af9d9 --- build/mobile/devicemanager.py | 2 +- build/mobile/devicemanagerSUT.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/mobile/devicemanager.py b/build/mobile/devicemanager.py index 9c5ce3e941e9..4127e100b5b0 100755 --- a/build/mobile/devicemanager.py +++ b/build/mobile/devicemanager.py @@ -438,7 +438,7 @@ class DeviceManager: id - unique id of the device uptime - uptime of the device uptimemillis - uptime of the device in milliseconds (NOT supported on all - platforms) + implementations) systime - system time of the device screen - screen resolution memory - memory stats diff --git a/build/mobile/devicemanagerSUT.py b/build/mobile/devicemanagerSUT.py index d1e7ae46d76d..4f40023d9005 100644 --- a/build/mobile/devicemanagerSUT.py +++ b/build/mobile/devicemanagerSUT.py @@ -918,7 +918,7 @@ class DeviceManagerSUT(DeviceManager): # os - name of the os # id - unique id of the device # uptime - uptime of the device - # uptimemillis - uptime of the device in milliseconds + # uptimemillis - uptime of the device in milliseconds (SUTAgent 1.11+) # systime - system time of the device # screen - screen resolution # rotation - rotation of the device (in degrees) From 45f60304ccdac72ea419970ebbc30ce0482dbf5f Mon Sep 17 00:00:00 2001 From: Marcos Santiago Date: Mon, 6 Aug 2012 01:03:00 +1200 Subject: [PATCH 163/169] Bug 758950 - Part 1: Use more for...of loops in Add-ons Manager frontend and backend code. r=Unfocused --- .../mozapps/extensions/AddonRepository.jsm | 24 +++++++++---------- .../mozapps/extensions/content/extensions.js | 15 ++++++------ .../extensions/content/xpinstallConfirm.js | 16 ++++++------- .../extensions/content/xpinstallConfirm.xul | 2 +- .../test/browser/browser_bug557956.js | 20 ++++++++-------- .../extensions/test/xpcshell/head_addons.js | 6 ++--- 6 files changed, 41 insertions(+), 42 deletions(-) diff --git a/toolkit/mozapps/extensions/AddonRepository.jsm b/toolkit/mozapps/extensions/AddonRepository.jsm index ac721ce26c0a..61d780ae52fa 100644 --- a/toolkit/mozapps/extensions/AddonRepository.jsm +++ b/toolkit/mozapps/extensions/AddonRepository.jsm @@ -1023,11 +1023,11 @@ var AddonRepository = { break; case "authors": let authorNodes = node.getElementsByTagName("author"); - Array.forEach(authorNodes, function(aAuthorNode) { - let name = self._getDescendantTextContent(aAuthorNode, "name"); - let link = self._getDescendantTextContent(aAuthorNode, "link"); + for (let authorNode of authorNodes) { + let name = self._getDescendantTextContent(authorNode, "name"); + let link = self._getDescendantTextContent(authorNode, "link"); if (name == null || link == null) - return; + continue; let author = new AddonManagerPrivate.AddonAuthor(name, link); if (addon.creator == null) @@ -1038,27 +1038,27 @@ var AddonRepository = { addon.developers.push(author); } - }); + } break; case "previews": let previewNodes = node.getElementsByTagName("preview"); - Array.forEach(previewNodes, function(aPreviewNode) { - let full = self._getUniqueDescendant(aPreviewNode, "full"); + for (let previewNode of previewNodes) { + let full = self._getUniqueDescendant(previewNode, "full"); if (full == null) - return; + continue; let fullURL = self._getTextContent(full); let fullWidth = full.getAttribute("width"); let fullHeight = full.getAttribute("height"); let thumbnailURL, thumbnailWidth, thumbnailHeight; - let thumbnail = self._getUniqueDescendant(aPreviewNode, "thumbnail"); + let thumbnail = self._getUniqueDescendant(previewNode, "thumbnail"); if (thumbnail) { thumbnailURL = self._getTextContent(thumbnail); thumbnailWidth = thumbnail.getAttribute("width"); thumbnailHeight = thumbnail.getAttribute("height"); } - let caption = self._getDescendantTextContent(aPreviewNode, "caption"); + let caption = self._getDescendantTextContent(previewNode, "caption"); let screenshot = new AddonManagerPrivate.AddonScreenshot(fullURL, fullWidth, fullHeight, thumbnailURL, thumbnailWidth, thumbnailHeight, caption); @@ -1066,11 +1066,11 @@ var AddonRepository = { if (addon.screenshots == null) addon.screenshots = []; - if (aPreviewNode.getAttribute("primary") == 1) + if (previewNode.getAttribute("primary") == 1) addon.screenshots.unshift(screenshot); else addon.screenshots.push(screenshot); - }); + } break; case "learnmore": addon.homepageURL = addon.homepageURL || this._getTextContent(node); diff --git a/toolkit/mozapps/extensions/content/extensions.js b/toolkit/mozapps/extensions/content/extensions.js index 58bb3ea44e8a..da9aafd68c86 100644 --- a/toolkit/mozapps/extensions/content/extensions.js +++ b/toolkit/mozapps/extensions/content/extensions.js @@ -2422,8 +2422,7 @@ var gListView = { return; let prop = aIsInstall ? "mInstall" : "mAddon"; - for (let i = 0; i < this._listBox.itemCount; i++) { - let item = this._listBox.childNodes[i]; + for (let item of this._listBox.childNodes) { if (item[prop] == aObj) return; } @@ -2436,8 +2435,7 @@ var gListView = { removeItem: function gListView_removeItem(aObj, aIsInstall) { let prop = aIsInstall ? "mInstall" : "mAddon"; - for (let i = 0; i < this._listBox.itemCount; i++) { - let item = this._listBox.childNodes[i]; + for (let item of this._listBox.childNodes) { if (item[prop] == aObj) { this._listBox.removeChild(item); this.showEmptyNotice(this._listBox.itemCount == 0); @@ -2653,12 +2651,13 @@ var gDetailView = { !gViewController.commands.cmd_showItemPreferences.isEnabled(aAddon); var gridRows = document.querySelectorAll("#detail-grid rows row"); - for (var i = 0, first = true; i < gridRows.length; ++i) { - if (first && window.getComputedStyle(gridRows[i], null).getPropertyValue("display") != "none") { - gridRows[i].setAttribute("first-row", true); + let first = true; + for (let gridRow of gridRows) { + if (first && window.getComputedStyle(gridRow, null).getPropertyValue("display") != "none") { + gridRow.setAttribute("first-row", true); first = false; } else { - gridRows[i].removeAttribute("first-row"); + gridRow.removeAttribute("first-row"); } } diff --git a/toolkit/mozapps/extensions/content/xpinstallConfirm.js b/toolkit/mozapps/extensions/content/xpinstallConfirm.js index 3f6d214940ee..242859cb6ede 100644 --- a/toolkit/mozapps/extensions/content/xpinstallConfirm.js +++ b/toolkit/mozapps/extensions/content/xpinstallConfirm.js @@ -30,25 +30,25 @@ XPInstallConfirm.init = function () var itemList = document.getElementById("itemList"); var numItemsToInstall = args.installs.length; - for (var i = 0; i < numItemsToInstall; ++i) { + for (let install of args.installs) { var installItem = document.createElement("installitem"); itemList.appendChild(installItem); - installItem.name = args.installs[i].addon.name; - installItem.url = args.installs[i].sourceURI.spec; - var icon = args.installs[i].iconURL; + installItem.name = install.addon.name; + installItem.url = install.sourceURI.spec; + var icon = install.iconURL; if (icon) installItem.icon = icon; - var type = args.installs[i].type; + var type = install.type; if (type) installItem.type = type; - if (args.installs[i].certName) { - installItem.cert = bundle.getFormattedString("signed", [args.installs[i].certName]); + if (install.certName) { + installItem.cert = bundle.getFormattedString("signed", [install.certName]); } else { installItem.cert = bundle.getString("unverified"); } - installItem.signed = args.installs[i].certName ? "true" : "false"; + installItem.signed = install.certName ? "true" : "false"; } var introString = bundle.getString("itemWarnIntroSingle"); diff --git a/toolkit/mozapps/extensions/content/xpinstallConfirm.xul b/toolkit/mozapps/extensions/content/xpinstallConfirm.xul index a82381bd5ceb..f1c29eb73c3d 100644 --- a/toolkit/mozapps/extensions/content/xpinstallConfirm.xul +++ b/toolkit/mozapps/extensions/content/xpinstallConfirm.xul @@ -17,7 +17,7 @@ ondialogaccept="return XPInstallConfirm.onOK();" ondialogcancel="return XPInstallConfirm.onCancel();"> -