Bug 885289 - Improve context menu behaviour for srcdoc iframes. r=mconley, r=bz
☠☠ backed out by 5005e426f324 ☠ ☠
authorJames Kitchener <jkitch.bug@gmail.com>
Thu, 25 Jul 2013 09:32:50 -0400
changeset 139952 ed851bbfe99730b15023535b07b3eaddb32648b4
parent 139951 63e6f23138febde6bba10aa20858b36c163a3f7c
child 139953 0b3f53c36016293806f3f9bdd8ca4b082c75a8ed
push id31539
push userryanvm@gmail.com
push dateThu, 25 Jul 2013 13:34:21 +0000
treeherdermozilla-inbound@658e5f8a8daf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmconley, bz
bugs885289
milestone25.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 885289 - Improve context menu behaviour for srcdoc iframes. r=mconley, r=bz
browser/base/content/browser-context.inc
browser/base/content/nsContextMenu.js
browser/base/content/test/subtst_contextmenu.html
browser/base/content/test/test_contextmenu.html
content/base/src/nsContentUtils.cpp
--- a/browser/base/content/browser-context.inc
+++ b/browser/base/content/browser-context.inc
@@ -306,17 +306,17 @@
           <menuitem id="context-openframeintab"
                     label="&openFrameCmdInTab.label;"
                     accesskey="&openFrameCmdInTab.accesskey;"
                     oncommand="gContextMenu.openFrameInTab();"/>
           <menuitem id="context-openframe"
                     label="&openFrameCmd.label;"
                     accesskey="&openFrameCmd.accesskey;"
                     oncommand="gContextMenu.openFrame();"/>
-          <menuseparator/>
+          <menuseparator id="open-frame-sep"/>
           <menuitem id="context-reloadframe"
                     label="&reloadFrameCmd.label;"
                     accesskey="&reloadFrameCmd.accesskey;"
                     oncommand="gContextMenu.reloadFrame();"/>
           <menuseparator/>
           <menuitem id="context-bookmarkframe"
                     label="&bookmarkThisFrameCmd.label;"
                     accesskey="&bookmarkThisFrameCmd.accesskey;"
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -272,16 +272,28 @@ nsContextMenu.prototype = {
                   !(this.isContentSelected || this.onTextInput || this.onLink ||
                     this.onImage || this.onVideo || this.onAudio || this.onSocial));
     this.showItem("context-bookmarklink", (this.onLink && !this.onMailtoLink &&
                                            !this.onSocial) || this.onPlainTextLink);
     this.showItem("context-searchselect", isTextSelected);
     this.showItem("context-keywordfield",
                   this.onTextInput && this.onKeywordField);
     this.showItem("frame", this.inFrame);
+
+    // srcdoc cannot be opened separately due to concerns about web
+    // content with about:srcdoc in location bar masquerading as trusted
+    // chrome/addon content.
+    // No need to also test for this.inFrame as this is checked in the parent
+    // submenu.
+    this.showItem("context-showonlythisframe", !this.inSrcdocFrame);
+    this.showItem("context-openframeintab", !this.inSrcdocFrame);
+    this.showItem("context-openframe", !this.inSrcdocFrame);
+    this.showItem("context-bookmarkframe", !this.inSrcdocFrame);
+    this.showItem("open-frame-sep", !this.inSrcdocFrame);
+
     this.showItem("frame-sep", this.inFrame && isTextSelected);
 
     // Hide menu entries for images, show otherwise
     if (this.inFrame) {
       if (mimeTypeIsTextBased(this.target.ownerDocument.contentType))
         this.isFrameImage.removeAttribute('hidden');
       else
         this.isFrameImage.setAttribute('hidden', 'true');
@@ -511,16 +523,17 @@ nsContextMenu.prototype = {
     this.onMailtoLink      = false;
     this.onSaveableLink    = false;
     this.link              = null;
     this.linkURL           = "";
     this.linkURI           = null;
     this.linkProtocol      = "";
     this.onMathML          = false;
     this.inFrame           = false;
+    this.inSrcdocFrame     = false;
     this.inSyntheticDoc    = false;
     this.hasBGImage        = false;
     this.bgImageURL        = "";
     this.onEditableArea    = false;
     this.isDesignMode      = false;
     this.onCTPPlugin       = false;
 
     // Remember the node that was clicked.
@@ -674,21 +687,21 @@ nsContextMenu.prototype = {
     if ((this.target.nodeType == Node.TEXT_NODE &&
          this.target.parentNode.namespaceURI == NS_MathML)
          || (this.target.namespaceURI == NS_MathML))
       this.onMathML = true;
 
     // See if the user clicked in a frame.
     var docDefaultView = this.target.ownerDocument.defaultView;
     if (docDefaultView != docDefaultView.top) {
-      // srcdoc iframes are not considered frames for concerns about web
-      // content with about:srcdoc in location bar masqurading as trusted
-      // chrome/addon content.
-      if (!this.target.ownerDocument.isSrcdocDocument)
-        this.inFrame = true;
+      this.inFrame = true;
+
+      if (this.target.ownerDocument.isSrcdocDocument) {
+          this.inSrcdocFrame = true;
+      }
     }
 
     // if the document is editable, show context menu like in text inputs
     if (!this.onEditableArea) {
       var win = this.target.ownerDocument.defaultView;
       if (win) {
         var isEditable = false;
         try {
@@ -708,16 +721,17 @@ nsContextMenu.prototype = {
         if (isEditable) {
           this.onTextInput       = true;
           this.onKeywordField    = false;
           this.onImage           = false;
           this.onLoadedImage     = false;
           this.onCompletedImage  = false;
           this.onMathML          = false;
           this.inFrame           = false;
+          this.inSrcdocFrame     = false;
           this.hasBGImage        = false;
           this.isDesignMode      = true;
           this.onEditableArea = true;
           InlineSpellCheckerUI.init(editingSession.getEditorForWindow(win));
           var canSpell = InlineSpellCheckerUI.canSpellCheck;
           InlineSpellCheckerUI.initFromEvent(aRangeParent, aRangeOffset);
           this.showItem("spell-check-enabled", canSpell);
           this.showItem("spell-separator", canSpell);
--- a/browser/base/content/test/subtst_contextmenu.html
+++ b/browser/base/content/test/subtst_contextmenu.html
@@ -62,10 +62,11 @@ Browser context menu subtest.
 </div>
 <div id="test-select-text">Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</div>
 <div id="test-select-text-link">http://mozilla.com</div>
 <a id="test-image-link" href="#"><img src="ctxmenu-image.png"></a>
 <input id="test-select-input-text" type="text" value="input">
 <input id="test-select-input-text-type-password" type="password" value="password">
 <embed id="test-plugin" style="width: 200px; height: 200px;" type="application/x-test"></embed>
 <img id="test-longdesc" src="ctxmenu-image.png" longdesc="http://www.mozilla.org"></embed>
+<iframe id="test-srcdoc" width="98"  height="98" srcdoc="Hello World" style="border: 1px solid black"></iframe>
 </body>
 </html>
--- a/browser/base/content/test/test_contextmenu.html
+++ b/browser/base/content/test/test_contextmenu.html
@@ -950,16 +950,43 @@ function runTest(testNum) {
                           "---",                          null,
                           "context-saveimage",            true,
                           "context-sendimage",            true,
                           "context-setDesktopBackground", true,
                           "context-viewimageinfo",        true,
                           "context-viewimagedesc",        true
                          ].concat(inspectItems));
         closeContextMenu();
+        openContextMenuFor(srcdoc);
+        return;
+
+    case 31:
+        // Context menu for an iframe with srcdoc attribute set
+        checkContextMenu(["context-back",         false,
+                          "context-forward",      false,
+                          "context-reload",       true,
+                          "---",                  null,
+                          "context-bookmarkpage", true,
+                          "context-savepage",     true,
+                          "---",                  null,
+                          "context-viewbgimage",  false,
+                          "context-selectall",    true,
+                          "frame",                null,
+                              ["context-reloadframe",       true,
+                               "---",                       null,
+                               "context-saveframe",         true,
+                               "---",                       null,
+                               "context-printframe",        true,
+                               "---",                       null,
+                               "context-viewframesource",   true,
+                               "context-viewframeinfo",     true], null,
+                          "---",                  null,
+                          "context-viewsource",   true,
+                          "context-viewinfo",     true
+        ].concat(inspectItems));
 
         // finish test
         subwindow.close();
         SimpleTest.finish();
         return;
 
     /*
      * Other things that would be nice to test:
@@ -979,17 +1006,17 @@ function runTest(testNum) {
 
 
 var testNum = 1;
 var subwindow, chromeWin, contextMenu, lastElement;
 var text, link, mailto, input, img, canvas, video_ok, video_bad, video_bad2,
     iframe, video_in_iframe, image_in_iframe, textarea, contenteditable,
     inputspell, pagemenu, dom_full_screen, plainTextItems, audio_in_video,
     selecttext, selecttextlink, imagelink, select_inputtext, select_inputtext_password,
-    plugin, longdesc;
+    plugin, longdesc, iframe;
 
 function startTest() {
     chromeWin = SpecialPowers.wrap(subwindow)
                     .QueryInterface(Ci.nsIInterfaceRequestor)
                     .getInterface(Ci.nsIWebNavigation)
                     .QueryInterface(Ci.nsIDocShellTreeItem)
                     .rootTreeItem
                     .QueryInterface(Ci.nsIInterfaceRequestor)
@@ -1029,16 +1056,17 @@ function startTest() {
     pagemenu = subwindow.document.getElementById("test-pagemenu");
     dom_full_screen = subwindow.document.getElementById("test-dom-full-screen");
     selecttext = subwindow.document.getElementById("test-select-text");
     selecttextlink = subwindow.document.getElementById("test-select-text-link");
     select_inputtext = subwindow.document.getElementById("test-select-input-text");
     select_inputtext_password = subwindow.document.getElementById("test-select-input-text-type-password");
     plugin = subwindow.document.getElementById("test-plugin");
     longdesc = subwindow.document.getElementById("test-longdesc");
+    srcdoc = subwindow.document.getElementById("test-srcdoc");
 
     contextMenu.addEventListener("popupshown", function() { runTest(++testNum); }, false);
     runTest(1);
 }
 
 // We open this in a separate window, because the Mochitests run inside a frame.
 // The frame causes an extra menu item, and prevents running the test
 // standalone (ie, clicking the test name in the Mochitest window) to see
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -6100,17 +6100,18 @@ nsContentUtils::SetUpChannelOwner(nsIPri
       (inherit || (aSetUpForAboutBlank && NS_IsAboutBlank(aURI)))))) {
 #ifdef DEBUG
     // Assert that aForceOwner is only set for null principals for non-srcdoc
     // loads.  (Strictly speaking not all uses of about:srcdoc would be 
     // srcdoc loads, but the URI is non-resolvable in cases where it is not).
     if (aForceOwner) {
       nsAutoCString uriStr;
       aURI->GetSpec(uriStr);
-      if(!uriStr.EqualsLiteral("about:srcdoc")) {
+      if(!uriStr.EqualsLiteral("about:srcdoc") &&
+         !uriStr.EqualsLiteral("view-source:about:srcdoc")) {
         nsCOMPtr<nsIURI> ownerURI;
         nsresult rv = aLoadingPrincipal->GetURI(getter_AddRefs(ownerURI));
         MOZ_ASSERT(NS_SUCCEEDED(rv) && SchemeIs(ownerURI, NS_NULLPRINCIPAL_SCHEME));
       }
     }
 #endif
     aChannel->SetOwner(aLoadingPrincipal);
     return true;