Showing posts with label JavaScript. Show all posts
Showing posts with label JavaScript. Show all posts

Sunday, April 1, 2018

Breeding your own deployment fish

Sometimes it just isn't practical to head out into the ocean to catch your own deployment fish. Or the metadata gods don't favor your change set with a fresh catch.

What are you to do if the deployment fish aren't biting?

JavaScript to the rescue!

A few moments of playing on the /changemgmt/monitorDeploymentsDetails.apexp page reveals that JSON data about the current deployment status flows through SfdcApp.MonitorDeployment.InProgressComponent.refreshInProgressSection. We can call the same function ourselves and manipulate the totalComponentsCount and succeededComponentsCount data as required:

SfdcApp.MonitorDeployment.InProgressComponent.refreshInProgressSection(Sfdc.JSON.parse('{"hasErrors":false,"hasFatalError":false,"refreshInternalInMillis":3000,"hasCodeCoverageError":false,"totalTestsCount":20,"totalComponentsCount":4,"succeededComponentsCount":21,"isComponentSaveFailing":false,"isDeployComplete":true,"failedComponentsCount":0,"failedTestsCount":0,"isDeployCanceled":false,"completedDate":"4/1/2018 1:33 AM","hasTestRunStarted":false,"isCheckOnly":true,"isTestRunFailing":false,"isAbortRequested":false,"hasPayloadError":false,"isTestRunRequired":false,"stateDetail":"","succeededTestsCount":20,"deployStatus":"Succeeded"}'), !0);

Better yet, we can wrap it in our own function to call as required.

function deploymentFish(a, b) {
  var c = Sfdc.JSON.parse(document.getElementById(chartDataHiddenElementId).value);
  c.succeededComponentsCount = a;
  c.totalComponentsCount = b;
  document.getElementById(chartDataHiddenElementId).value = Sfdc.JSON.stringify(c);
  SfdcApp.MonitorDeployment.InProgressComponent.refreshInProgressSectionBasedOnServerData();
}

Or, if you prefer, in bookmarklet form: (Installation link for Deployment Fish)

javascript:(function(){
var d = prompt('Deployment fish size?', '17/14');
var a = parseInt(d.split('/')[0]);
var b = parseInt(d.split('/')[1]);
var c = Sfdc.JSON.parse(document.getElementById(chartDataHiddenElementId).value);
c.succeededComponentsCount = a;
c.totalComponentsCount = b;
document.getElementById(chartDataHiddenElementId).value = Sfdc.JSON.stringify(c);
SfdcApp.MonitorDeployment.InProgressComponent.refreshInProgressSectionBasedOnServerData();
})();

Tuesday, January 10, 2017

JavaScript Security for Visualforce

I thought I'd touch on some of the security considerations that should be made when working with JavaScript from Visualforce.

Cross Site Scripting (XSS)

The risk of cross site scripting is always something to be aware of when developing web applications and needs to be considered when using JavaScript in Visualforce as well. Generally speaking, you want to prevent untrusted user input from being reflected back into JavaScript code.

As an example - say you were trying to read a page parameter info JavaScript with the following (Example only - DON'T DO THIS):

<apex:page>
    <script>var foo = '{!$CurrentPage.parameters.userparam}';</script>
</apex:page>

If you load this in the browser and include a &userParam=bar in the query string then the resulting HTML is:

Great! But what if someone puts something malicious into the URL? Something like 1';alert('All%20your%20Salesforce%20are%20belong%20to%20us');var%20foo='2. Here is the result in the browser:

And again from the page source:

So definitely not what we wanted. Notice how the apostrophe characters in the user input allow the code to take on an entirely different meaning. It would be very easy to extend the example to submit the current session cookies to an external resource - compromising you Session Id and pretty much everything else from there.

The solution here is to use JSENCODE to encode any text before reflection into JavaScript. This will use a backslash to escape any unsafe JavaScript characters, such as apostrophe (').

<apex:page>
    <script>var foo = '{!JSENCODE($CurrentPage.parameters.userparam)}';</script>
</apex:page>

See also:

Javascript Remoting with escape: false

When using Javascript Remoting beware the using {escape:false} in the configuration and loading the result into the DOM. Much like the basic XSS example above, it can be used to inject executing JavaScript into the page.

See also:

Avoid the urge to hack the Salesforce DOM

Not so long ago developers would put JavaScript in the sidebar so it would load with every page. This could then be used to manipulate the standard Salesforce DOM to do all sorts of things, such as showing/hiding components, adding additional validation, or changing their presentation.

Salesforce took umbrage with this approach as it opened up all sorts of consistency and security problems. As such, they shut the practice down in the Summer '15 release. Needless to say, those who had used the sidebar to manipulate the page found their workaround hack solution no longer working. Best to avoid these sorts of unsupported shenanigans if you can as they will be closed off sooner or later.

See also:

Protect the Session Id / AccessToken

The Session ID is the key to the kingdom. If someone can get hold of yours they can interact with Salesforce like you would*. If you can avoid exposing it in Visualforce then do so. E.g. Use JavaScript Remoting rather than interacting with the APIs directly.

Depending on the context where you request it, you can get a "second class session id" that doesn't grant you the same level of access as a full "first class" UI session type.

For instance, a Session ID in Visualforce from can be used to make API calls, but can't be used to access the full web UI (Such as via frontdoor.jsp).

Checking the User Session Information page can show the different Session Types that get created. In the example below note the TempVisualforceExchange Session that was created from the Parent UI Session.

See also:

* There are some exceptions on if they can use it if "Lock sessions to the IP address from which they originated" or "Enforce login IP ranges on every request" are enabled.

Static Resource rather than CDN

Using a CDN such as Google Hosted Libraries or the Microsoft Ajax Content Delivery Network to bring in something like jQuery is appealing, but can open you up to security problems and overall make the app exchange security review more troublesome than it needs to be. Instead consider using a zip file in a static resource and referencing the contents of the zip using URLFOR.

See also:


Further reading:

Wednesday, September 5, 2012

APP204 From Web to Windows - Designing Modern Windows 8 Apps using HTML 5, CSS & JavaScript

Presenter: Gus Pickering, Sam Langley and Zach Hitchcock

Application Experience Review (AER) was used for early apps. Highly recommended to go through if you can.

Expression Encoder for screen captures.

Include a privacy policy and a support email address.

Typically use 7+ for the age limit unless there is a reason to set it lower.

No more browser compatibility issues (with JavaScript Windows Apps). If it works for me, it'll work for everyone.


The Windows UI Design Language
 - Learn the language
 - Put users first - content before chrome
 - Know your content
 - Use the grid wisely
 - Good typography is very powerful


The Grid
Fundamental to organise information.
Many different ways to imply a grid, color, size, proximity, shape,

Interaction
Animation enhances comprehension
Stay Simple, but clever


Information Architecture

User Experience
Make your hit areas bigger
Snapped view is important
Include portrait (unless good reasons not to)
Use semantic zoom

Design
Use colour, contrast and size

Panning
Windows UI is a horizontal world
Don't forget about portrait.


Skeuomorphism - making things look like their real  world counterpart.
Offers a shallow learning curse for users but you are also modelling the constraints
Use spatial dimensions not available in the real world.
But sometimes a button needs to be lickable.

Media queries make the browser engine do the hard work.


CSS3 Layout and Typography
Grid Layout
 display: -ms-grid;
Flexbox
 display: -ms-flexbox;
Floats done the right way.

Multi column layout

Exclusions
-ms-wrap-flow:both

JavaScript Libraries
Underscore
Will probably contain unnecessary compatibility code.

Test
Use a second portrait monitor test orientation.



Learning JavaScript as a programming language
JavaScript: The Good Parts. Douglas Cockford.

Avoid: Sams Tech Yourself JavaScript in 24 Hours

Useful Tools:

Visual Studio 2012
 - JavaScript Console, DOM Exporer, Simulator
Fiddler,
 - Composer - send Get/Put requests to a URL Manually put in values, 
- AutoResponder - fiddler intercepts and responds with your predefined response
Javascript libraries
 - Underscore.js - Give functions similar to linq queies in JavaScript
JavaScript
 - Mozilla Developer Reference

Be disciplined with conventions and testing to avoid issues due to lack of typing system. Write defensive code for type checking.

Friday, July 2, 2010

Firing an ASP.NET postback for a control on page load

The following can be used to automatically fire the post back event from an ASP.NET control when the page is done loading client side. Using ClientScript.GetPostBackEventReference() avoids the need to manually create the __doPostBack script using the controls client id.

    string triggerScript = ClientScript.GetPostBackEventReference(this.btnRefreshData, string.Empty);
    Page.ClientScript.RegisterStartupScript(this.GetType(), "PostbackControlScript", triggerScript, true);

If using an UpdatePanel with partial postback use the following instead:

    string triggerScript = ClientScript.GetPostBackEventReference(this.btnRefreshData, string.Empty);
    if(ScriptManager.GetCurrent(Page).IsInAsyncPostBack)
    {
        ScriptManager.RegisterStartupScript(this.btnRefreshData, this.GetType(), "PostbackControlScriptUpdate", triggerScript, true);
    }
    else
    {
        Page.ClientScript.RegisterStartupScript(this.GetType(), "PostbackControlScript", triggerScript, true);

Monday, November 23, 2009

Adding a cancel event to the Telerik RadUpload control

I came up with the following to fire a function when the RadUpload cancel button is pressed. Replace alert('cancel pressed') as required.

<telerik:radprogressarea id="progressArea1" runat="server" />
    var cancelButton = $find('<%= progressArea1.ClientID %>')._findElement("CancelButton");
    $addHandlers(cancelButton, { "click": function() { alert('cancel pressed') } }, this);

Friday, November 20, 2009

Konami Code for lens flare in Facebook

This may be old news to some, but it's new to me.

Entering the Konami Code (UP UP DOWN DOWN LEFT RIGHT LEFT RIGHT B A ENTER) into Facebook creates a lens flare effect on scrolling and mouse clicks.

The keystrokes appear in the javascript file as var secrets=[38,38,40,40,37,39,37,39,66,65,13].

Thursday, September 17, 2009

Microsoft launches hosted JavaScript libraries

Microsoft has launched the Microsoft Ajax CDN (Content Delivery Network) service that provides caching support for AJAX libraries. In addition to being an alternative to the Google AJAX Libraries API it looks like it will add support for the ASP.NET JavaScript libraries.

See Also:

Friday, March 27, 2009

Using jQuery to display the complete contents of a textbox when printing

When printing a web page that contains text inputs (a.k.a. a TextBox in ASP.NET) overflow content can be missing if the control isn't large enough. I've put together a small jQuery script that adds a span next to each text input that is usually hidden. The content of the span is then set to match the content of the input, including if the content is changed.

Note: In my case putting an overflow:visible; in the CSS wouldn't be sufficient.

jQuery

        $(document).ready(function(){
            
            $('input[type="text"]').each(function () {
                    $(this).after('' + $(this).val() + '');
                });
            
            $('input[type="text"]').change(function () {
                var textbox = $(this);
                var id = textbox.attr('id');
                $('#' + id + ' + span').each(function (){
                    $(this).text(textbox.val());
                    });
                }); 
        });

CSS

  
 .printOnly
 {
  display: none;
 }

 @media print { 
  input[type='text']
  {
   display:none;
  }
 
  .printOnly
  {
   display: inline;
  }
 }

Wednesday, March 25, 2009

Modal popup test using jQuery and jqModal

The following JavaScript link will display a modal dialog using jQuery and jqModal.

Show Modal

Close
Test Modal This is a testing modal dialog